We had a debate in our team for identifying what are the best practices for writing JUnit Test cases for DAO classes.
Let’s consider an object Foo whose DAO is something like this:
Interface FooDAO{
getById(id);
delete(foo);
save(foo);
}
A corresponding test case for this FooDAO will be:
FooDAOTestCase{
setup(){
//Save Foo object to use in test
Foo fooToTest = new Foo();
//Either use save()
fooDAO.save(fooToTest)
//or use low level api
connection.executeQuery(“INSERT INTO FOO_TABLE values(1,’bar’);
}
testGetById(){
}
testDelete(){
}
testSave(){
}
}
Now in order to write test cases for testGetById and testDelete I have to make sure that there exists a Foo in DB. I can either use the save() or write a low level API like using jdbcTemlpate if I am using Spring to save it.
My colleagues were arguing that we should be using the already existing save() in the Setup() because of the following reasons:-
- It already exists, don’t need to write code avoiding overhead
- If the schema changes there will be only one place to change the SQL Query
- If testGetById fails because save() failed we will find out where to go and fix it!
But, I insist on writing code separately to insert Foo instead of using save() for the following reasons:
- The big reason is to avoid dependency to other code or method. That means if I am testing getById(), the scope of this test should be only this method. This is one of the best practices of using JUnit.
- If I am doing Test Driven Development (TDD), I can copy those SQL statements into the production code.
I guess I will continue writing separate code in the future and advocating it in the future 🙂