karim karim - 24 days ago 5
Java Question

Junit test on DAO layer returns wrong results for postgresql exists() query

I'm testing my DAO layer using junit spring and jdbcTemplate. I have for instance an Address class and an AddressDAO, and i've implemented a method exists(long id) that return true if the given Address id exits in the database and false otherwise:

private static final String EXISTS_SQL = "SELECT EXISTS(SELECT * FROM \"ADDRESS\" WHERE id_address = ?)";

public boolean exists(long id){

return this.jdbcTemplate.query(AddressDAOImpl.EXISTS_SQL,
new Object[]{id},
new ResultSetExtractor<Boolean>() {

@Override
public Boolean extractData(ResultSet resultSet) throws SQLException,DataAccessException {

boolean result = resultSet.next();
return result;
}
});
}


But when i execute the following junit test it fails:

@Test
@Transactional
@Rollback(true)
public void testExists(){

Candidate c = new Candidate();
c.setEmail("email74");
c.setPassword("password");

candidateDAO.insert(c);

Address a1 = new Address();
a1.setRegistredUser(c);

addressDAO.insert(a1, c.getId());

boolean exists = addressDAO.exists(a1.getId());

Address a2 = new Address();
a2.setRegistredUser(c);

addressDAO.insert(a2, c.getId());
addressDAO.delete(a2);

boolean dontExists = addressDAO.exists(a2.getId());

System.out.println("exists = " + exists);
System.out.println("dontExists = " + dontExists);

Assert.assertTrue(exists == true);
Assert.assertTrue(dontExists == false);
}


The exists method returns true if i insert an address and when i delete it

exists = true
dontExists = true


I don't understand why... Is it because it's executed inside a transaction and the address is maybe deleted at the end of it?

Thank you for helping.

Answer

This is because you're using the SELECT EXISTS([...]) in your SQL. This statement always returns a single row containing either true or false(0 or 1) and thus resultSet.next() always finds a row and since this function returns true if it did find a row you always get that true.

If you want to check it this way, I suggest you simply remove the outer select(SELECT EXISTS) and only keep the inner. This way if no rows are found .next() will return false. You should also not select all columns(using *), but a single column(preferably one with an index e.g. simply the primary key).

Comments