I am new to JUnit and testing and am seriously at my wits end with this error:
expected:<null> but was: expected:<null> but was:<Order ID: 1, Customer ID: 1, Customer Name: jordan harrison, Item ID: 1, Item Name: Call of Duty, Quantity: 0, Total Cost: 0.0>
I have no idea why the below test does not work whatsoever. I have looked at other similar questions but they don't help my understanding of the tests at all and left me at a complete loss for how to fix this.
Here's the test:
public class OrderDAOTest {
private final OrderDAO DAO = new OrderDAO();
#Before
public void setup() {
DBUtils.connect();
DBUtils.getInstance().init("src/test/resources/sql-schema.sql", "src/test/resources/sql-data.sql");
}
#Test
public void testRead() {
Long oId = 1L;
Long iId = 1L;
Long cId = 1L;
String iName = "Call of Duty";
double iCost = 25.99;
Item item = new Item(iId, iName, iCost);
Customer customer = new Customer(cId);
CustomerDAO custDao = new CustomerDAO();
customer = custDao.read(customer.getCustomerId());
Order order = new Order();
order.setOrderId(1L);
order.setItem(item);
order.setCustomer(customer);
System.out.println(order);
assertEquals(DAO.read(order.getOrderId()), order);
}
This is the read() method with the orderItemsFromResultSet() method that it returns in the OrderDAO Class:
public Order orderItemsFromResultSet(ResultSet rs) throws SQLException {
Long orderId = rs.getLong("fk_order_id");
Long itemId = rs.getLong("item_id");
String itemName = rs.getString("item_name");
double itemCost = rs.getDouble("item_cost");
Item item = new Item(itemId, itemName, itemCost);
Order order = new Order(item, orderId);
return order;
}
#Override
public Order read(Long id) {
try (Connection connection = DBUtils.getInstance().getConnection();
PreparedStatement statement = connection.prepareStatement("SELECT * FROM order_items LEFT OUTER JOIN items ON items.item_id = order_items.fk_item_id WHERE fk_order_id = ?");) {
statement.setLong(1, id);
try (ResultSet resultSet = statement.executeQuery();) {
resultSet.next();
return orderItemsFromResultSet(resultSet);
}
} catch (Exception e) {
LOGGER.debug(e);
LOGGER.error(e.getMessage());
}
return null;
}
I just don't understand it and need help with understanding testing altogether.
You are catching all exceptions and then just returning null. There are two possible places I would debug further.
Check if the Connection is working fine.
Check if the query execution works fine too. Remove the semicolon at the end of the query and it may work.
The logs may help you here.
Related
I've got an Android Room database setup and followed some tutorials with which I'm trying to extend what I've made. I have gotten a few queries to work but when I try to use a SELECT * WHERE query it returns all the records in the table not just the records with the expected ID.
The Query in the DAO
#Query("SELECT * FROM weapon_table WHERE fighter_id = :fighter_id" )
LiveData<List<Weapon>> getFighterWeapons(long fighter_id);
The Record Object
#Entity(tableName = "weapon_table",
foreignKeys = {
#ForeignKey(entity = com.Database.Fighter.class,
parentColumns = "fighter_id",
childColumns = "fighter_id"),
})
public class Weapon
{
#NonNull
String weapon_name;
#NonNull
#PrimaryKey(autoGenerate = true)
long weapon_id;
#NonNull
long fighter_id;
public Weapon(String weapon_name, long fighter_id)
{
this.weapon_name = weapon_name;
this.fighter_id = fighter_id;
}
public long getWeapon_id()
{
return weapon_id;
}
public void setWeapon_id(long weapon_id)
{
this.weapon_id = weapon_id;
}
public String getWeapon_name()
{
return weapon_name;
}
public void setWeapon_name(String weapon_name)
{
this.weapon_name = weapon_name;
}
public long getFighter_id()
{
return fighter_id;
}
public void setFighter_id(long fighter_id)
{
this.fighter_id = fighter_id;
}
}
When I call the following code all records are printed to the debug console but the current ID is also printed and stays the same in all cases.
public void onClickAddWeapon(View view)
{
List<Weapon> weapons = mWeaponViewModel.getFighterWeapons(fighter.getFighter_id()).getValue();
for(Weapon weapon: weapons )
{
Log.d("WEAPONDEBUG", "WEAPONNAME/ID: " +weapon.getWeapon_name() +'/'+ weapon.getFighter_id() );
Log.d("WEAPONDEBUG", "FIGHTERID: "+ fighter.getFighter_id() );
}
}
Fix was fairly simple , I had followed this google code labs tutorial and when I tried to extend it I forgot to actually assign the result of the query to the list held in the repository file. Thanks for the suggestions they put me in the right direction.
LiveData<List<Weapon>> getFighterWeapons(long fighter_id)
{
mWeaponDao.getFighterWeapons(fighter_id);
return mAllWeapons;
}
replaced with
LiveData<List<Weapon>> getFighterWeapons(long fighter_id)
{
mAllWeapons = mWeaponDao.getFighterWeapons(fighter_id);
return mAllWeapons;
}
your code should be working, but I think that the problem is defining with foreign keys. `
parentColumns = "fighter_id",
childColumns = "fighter_id"
can you remove it and try?
`
Try this
#Query("SELECT * FROM weapon_table WHERE fighter_id IN (:fighter_id)" )
LiveData<List<Weapon>> getFighterWeapons(long fighter_id);
I'm not sure whether I'm using JMockit incorrectly, or there's something amiss in my setup. I'm using JMockit 1.32 with JUnit 4.12 in Eclipse.
My problem seems to be that interfaces aren't being captured. Specifically in the java.sql package. For example:
public class Dto {
private int id;
public Dto(){}
public Dto(ResultSet rs) {
try {
id = rs.getInt(1);
} catch (SQLException e) { }
}
public int getId() {return id;}
void setId(int id) {this.id = id;}
}
.
public class ClassUnderTest {
public static Dto loadObject(Connection conn, String tablename, int id) {
Dto result = null;
ResultSet rs = null;
PreparedStatement ps = null;
try {
String sql = "select * from " + tablename + " where id = ?";
ps = conn.prepareStatement(sql);
ps.setInt(1, id);
rs = ps.executeQuery();
if (rs.next()) {
result = new Dto(rs);
}
} catch (SQLException e) {
} finally {
try {
if (ps != null) ps.close();
} catch (SQLException e) { }
}
return result;
}
}
.
public class ResultSetTest extends junit.framework.TestCase {
private static final int OBJ_ID = 5;
#Capturing
ResultSet mockResultSet;
#Capturing
PreparedStatement mockStatement;
#Capturing
Connection mockConn;
#Test
public void testGetDtoById() throws SQLException {
new Expectations() {{
mockConn.prepareStatement(anyString); result = mockStatement;
mockStatement.setInt(anyInt, OBJ_ID);
mockResultSet.next(); result = true;
new Dto(mockResultSet); result = new Dto();
mockResultSet.next(); result = true;
}};
Dto dto = ClassUnderTest.loadObject(mockConn, "", OBJ_ID);
assertEquals(dto.getId(), OBJ_ID);
}
}
In this setup, test execution fails with a NPE on the first line in the Expectations(){} block. But from the tutorials, etc. I'm expecting a mocked instance to have been created. (e.g. tutorial)
Trying to move past this, I created explicit mocked classes like so:
public class ResultSetMockup extends MockUp<ResultSet> { }
public class PreparedStatementMockup extends MockUp<PreparedStatement>
{
#Mock ResultSet executeQuery() {return new ResultSetMockup().getMockInstance();}
}
public class ConnectionMockup extends MockUp<Connection>
{
#Mock PreparedStatement prepareStatement(String sql) throws SQLException {
return new PreparedStatementMockup().getMockInstance();
}
}
#Capturing
ResultSet mockResultSet = new ResultSetMockup().getMockInstance();
#Capturing
PreparedStatement mockStatement = new PreparedStatementMockup().getMockInstance();
#Capturing
Connection mockConn = new ConnectionMockup().getMockInstance();
At this point, the Expectations() {} block is happy, but it appears that results is never actually being set. By setting a breakpoint I see that rs.next() always fails. So I presume nothing is actually being captured.
What am I doing wrong? Or is something in my setup preventing JMockit from actually running?
The actual problem in the test is that it's mixing the APIs from JUnit 3 (anything from junit.framework) and JUnit 4+ (org.junit). This should never be done.
JMockit only supports the JUnit 4 API, not the obsolete JUnit 3 API. So, simply remove "extends from junit.framework.TestCase" that it will be ok.
BTW, your Java IDE should have warned against this mistake. IntelliJ, at least, promptly displays "Method 'testGetDtoById()' annotated with '#Test' inside class extending JUnit 3 TestCase".
Also, the test (and the code under test) has several other mistakes...
My problem appears to have been the use of JUnit. I went as far as to try tutorial examples verbatim without luck. But by converting over to TestNG all my problems went away.
It seems as though JMockit's Expectations block wasn't able to hook into the code properly with JUnit. Either calls weren't recognized or the faking wasn't happening. I'm curious now, does anyone have it working with JUnit?
i have two table and i want insert or update table two with table one.first i select table one and add the result into the resultset.then i select all of the table two records and add them to a list.then i have a iteration on result set and check that if records of table one is in table two then update them and if there is no record of table one in table two persist the new record.but in my code every time persist happens or update is not right.
public static void main(String[] args) throws SQLException, ClassNotFoundException {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("/spring-servlet.xml");
PersonManager personManager = (PersonManager) applicationContext.getBean("x");
Person person=new Person();
person.setPerson_Name("nazanin");
person.setPerson_Family("qolamian");
person.setPerson_Kill("1");
personManager.registerPerson(person);
personManager.updatePerson();
}
and my personManager0:
public void updatePerson() throws ClassNotFoundException, SQLException {
String getClass = "oracle.jdbc.driver.OracleDriver";
String connectionStringOracle = "jdbc:oracle:thin:#localhost:1521:orcl";
String userSqlServer = "solaris";
String passSqlServer = "myjava123";
String queryStringSelectFromOracle="select * from people ORDER BY NAME ";
Class.forName(getClass);
Connection connection = DriverManager.getConnection(connectionStringOracle,userSqlServer ,passSqlServer );
Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
ResultSet resultSet = statement.executeQuery(queryStringSelectFromOracle);
List<Person> personList = entityManager.createQuery("select c from person c order by c.person_Name ASC ").getResultList();
for (Person person : personList) {
person.setPerson_Kill("0");
}
List<Person> personList1=new ArrayList<>();
while (resultSet.next()){
String rname = resultSet.getString("NAME");
String rfamily = resultSet.getString("FAMILY");
for (Person person : personList) {
String name = person.getPerson_Name();
String family = person.getPerson_Family();
if (name.equals(rname)){
if (family.equals(rfamily)){
person.setPerson_Kill("1");
break;
}else {
person.setPerson_Family(rfamily);
person.setPerson_Kill("1");
break;
}
}else if (family.equals(rfamily)){
person.setPerson_Name(rname);
person.setPerson_Kill("1");
break;
}else {
Person person1 = new Person();
person1.setPerson_Kill("1");
person1.setPerson_Family(rfamily);
person1.setPerson_Name(rname);
personList1.add(person1);
}
}
}
if (personList1.isEmpty()){
}else {
for (Person person : personList1) {
System.out.println("x");
registerPerson(person);
}
}
}
i realy want know how transactions work in spring when it begins and when it closes?can i manualy manage commits or close connections?
Spring use AOP to make declarative transaction works,of course,you can manually control transaction boundary.
remember,declarative transaction based on proxy in spring, so if you call a method directly, for example in your code snapshot,transaction on registerPerson() method will not work
declare a TransactionTemplate bean in your spring context.
autowire TransactionTemplate into your PersonManager
#Autowire
private TransactionTemplate txTemplate;
try following snapshot:
txTemplate.execute(new TransactionCallback<Void>(){
public Void doInTransaction(TransactionStatus txStatus){
try{
for (Person person : personList1) {
System.out.println("x");
registerPerson(person);
}
} catch(RuntimeException e){
txStatus.setRollbackOnly();
throw e;
}
return null;
}
});
I have a Java class with instance fields (and matching setter methods) that match the column names of a SQL database table. I would like to elegantly fetch a row from the table (into a ResultSet) and map it to an instance of this class.
For example:
I have a "Student" class with instance fields "FNAME", "LNAME", "GRADE" and appropriate getter and setter methods for each.
I also have a SQL table with three columns of the same name.
Right now I am doing something like this:
rs = statement.executeQuery(query);
Student student = new Student();
student.setFNAME(rs.getString("FNAME"));
student.setLNAME(rs.getString("LNAME"));
student.setGRADE(rs.getString("GRADE"));
There has to be a less verbose way of doing this, right? As I add columns this might get really annoying and messy.
I recommend using Spring JDBC. You don't need to use the rest of Spring to use their JDBC library. It will manage connections for you (no more closing Connection, Statement, or ResultSet) and has many conveniences, including row mapping.
We've retrofitted legacy code with Spring JDBC with little trouble.
Here is a presentation (PDF) of an overview of Spring JDBC. It's a few years old but it still works essentially the same, even without letting Spring inject the dependencies.
Spring JDBC Presentation PDF
You can do it generically by doing the following simple methods:
Interface to use as a method pointer:
public interface I_DBtoJavaObjectConvertable<T>
{
public T createFromDB(ResultSet i_rs) throws SQLException;
}
Generic class to handle every mapping from SQL to java Object:
public class DBManager
{
static volatile Connection conn;
//set here a static c'tor to handle the connection to the database
//The General generic method:
public static <T> List<T> GetObjectsFromDB(String i_Query, I_DBtoJavaObjectConvertable i_Converter)
{
List<T> ResList = new ArrayList<>();
try
{
Statement st = conn.createStatement();
for (ResultSet rs = st.executeQuery(i_Query); rs.next();)
{
ResList.add((T) i_Converter.createFromDB(rs));
}
}
catch (SQLException ex)
{
_LOG_ERROR(ex.getMessage());
}
return ResList;
}
}
Now By using Lanbda expression use can easlly convert an sql row to object, by given your convertion method, for example:
public static User FetchUserFromDB(ResultSet i_rs)
{
User userToCreate = null;
try
{
String FirstName = i_rs.getString("FirstName");
String LastName = i_rs.getString("LastName");
String Password = i_rs.getString("Password");
userToCreate = new User(FirstName, LastName, Password);
}
catch (SQLException ex)
{
_LOG_ERROR("Error in fetching user from DB: \n" + ex.getMessage());
}
return userToCreate;
}
And now you can use this this method to bring any Users you want:
public static List<User> GetAllUsersFromDB() throws SQLException
{
String Query = "select * "
+ "from UsersTable";
return DBManager.GetObjectsFromDB(Query, rs -> FetchUserFromDB(rs));
}
Or:
public static List<String> GetAllNamesFromDB() throws SQLException
{
String Query = "select FirstName "
+ "from UsersTable";
return DBManager.GetObjectsFromDB(Query, rs -> rs.getString("FirstName"));
}
You could use an ORM like one of the JPA providers e.g. Hibernate. This lets you set up mappings between your objects and your tables.
If you use JDBC that is how it works. If you want to avoid adding columns like this in Java, you may consider using some ORM frameworks.
A slightly less verbose way would be to give Student a constructor that accepts 3 strings. Then you could do this:
Student student = new Student(rs.getString("FNAME"), rs.getString("LNAME"), rs.getString("GRADE"));
The other way to do it is to use an ORM like Hibernate but Hibernate only becomes worth the massive setup effort for really big projects dealing with lots of tables.
There are many ORM libraries that simplify or eliminate the JDBC drudgery. See Source Forge ORM for some examples. I like my library, sormula, since it can be used with minimal configuration.
If you do not want to use any other framework, you can create standard mapping method and use it after every Result.
public class CurrencyDAO(){
public Currency findById(int id) {
String sql = "SELECT * FROM CCR.CURRENCY WHERE id = ?";
Currency currency = null;
Connection c = null;
try {
c = DBConnection.getConnection();
PreparedStatement ps = c.prepareStatement(sql);
ps.setInt(1, id);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
currency = processRow(rs);
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally {
DBConnection.close(c);
}
return currency;
}
protected Currency processRow(ResultSet rs) throws SQLException {
Currency currency = new Currency();
currency.setId(rs.getInt("id"));
currency.setEUR(rs.getString("EUR"));
currency.setUSD(rs.getString("USD"));
currency.setRate(rs.getString("rate"));
return currency;
}
}
Give q2o a try. It is a JPA based object mapper which helps you with many of the tedious SQL and JDBC ResultSet related tasks, but without all the complexity an ORM framework comes with.
Bind the Student class to its corresponding table:
#Table(name = "STUDENTS")
public class Student (
private String FNAME;
private String LNAME;
private String GRADE;
...
)
Select some students by their grade:
List<Student> students = Q2ObjList.fromClause(Student.class, "GRADE = ?", grade);
Change a student's grade and persist the change to the database:
student.setGRADE(grade);
Q2obj.update(student);
q2o is helpful even when you depend on Spring JDBC:
jdbcTemplate.queryForObject("...", new RowMapper<Student>() {
#Override
public Student mapRow(final ResultSet rs, final int rowNum) throws SQLException {
return Q2Obj.fromResultSet(rs, Student.class);
}
});
It is pretty easy, isn't it? Find more about q2o here.
When you execute a query you can get metadata from the ResultSet. You have access to the columns from this. Here's an example:
#RestController
public class MyController {
#GetMapping("/characters")
public List<Payload> characters() {
List<Payload> results = new ArrayList<>();
try (Connection conn = new Connection()) {
conn.makeConnection();
Statement stmt = conn.createStatement();
ResultSet result = stmt.executeQuery("SELECT * FROM public.hello;");
ResultSetMetaData resultMetaData = result.getMetaData();
Set<String> columns = new HashSet<>();
for (int i = 1; i <= resultMetaData.getColumnCount(); i++) {
columns.add(resultMetaData.getColumnName(i));
}
while (result.next()) {
results.add(new Data(result, columns));
}
} catch (Exception e) {
results.add(new Fail("404", e.getMessage()));
}
return results;
}
}
public class Data implements Payload {
private final Map<String, Object> data = new HashMap<>();
public Data(ResultSet result, Set<String> columns) throws SQLException {
for (String column : columns) {
data.put(column, result.getString(column));
}
}
public Map<String, Object> getData() {
return data;
}
}
Now you can have one class object that parses out the columns and data for any table. You never really care what columns there are. The down side is that all of your info is now stored in a data field. So the payload would look something like:
[
{"data":{"id":"1","name":"Rick Sanchez"}},
{"data":{"id":"2","name":"Morty Smith"}},
{"data":{"id":"3","message":"Summer Smith"}}
]
I've an array keeping a list of Group objects. I want to set this list to the DropDownChoice component. However I want to show the end user only the name attribute of Group objects, and then get the selected values' id attribute to add database. What to do?
private List<Group> groupTypes;
DatabaseApp db = new DatabaseApp();
groupTypes = db.getGroups();
groupDropDownChoice = new DropDownChoice("type", groupTypes);
...
...
addUserForm.add(new Button("submit"){
#Override
public void onSubmit(){
Group group = (Group) groupDropDownChoice.getModelObject();
...
...
db.addUser(group.getId(), den, name, login, email, password1);
DatabaseApp.java
public List<Group> getGroups() throws SQLException{
List<Group> groups = new ArrayList<Group>();
try {
String query = "SELECT * FROM [GROUP]";
Statement statement = db.createStatement();
ResultSet result = statement.executeQuery(query);
while(result.next()){
int id = result.getInt("ID");
String name = result.getString("NAME");
groups.add(new Group(id, name));
}
result.close();
} catch (SQLException ex) {
throw new SQLException(ex.getMessage());
}
return groups;
}
DropDownChoice has another constructor accepting an additional parameter of an IChoiceRenderer that allows control of what's displayed and what's sent back with the form.
See this example.
In your code, an implementation could look approximately like
private List<Group> groupTypes;
DatabaseApp db = new DatabaseApp();
groupTypes = db.getGroups();
groupDropDownChoice = new DropDownChoice("type", groupTypes, new IChoiceRenderer(){
#Override
public Object getDisplayValue(Object object) {
return ((Group) object).getName();
}
#Override
public String getIdValue(Object object, int index) {
return Integer.toString(index);
}
});
...
...
addUserForm.add(new Button("submit"){
#Override
public void onSubmit(){
Group group = (Group) groupDropDownChoice.getModelObject();
...
...
db.addUser(group.getId(), den, name, login, email, password1);
You're just creating the DropDownChoice directly from the list of groups. It seems to me that what you really want is a model for the list of groups; see the IModel documentation. Then you can create a custom model that returns only the name of a group instead of the whole Group object.