berk geylani berk geylani - 4 months ago 10
Java Question

Should i call methods from class which is testing when i unit test?

I have a database helper class which does insert,delete,save,connect,etc and i am writing test for this.However, when i write a test case should it be independent from testing class?

Should it be like:
1-)

@Test
public void testDelete() throws SQLException {
// Given
String dateStr = "09-May-2016";
String word = "testWord";
derbyDb.save(dateStr, word, 9);
derbyDb.save(dateStr, word, 11);

// When
assertEquals(2, derbyDb.contain(dateStr, word));
derbyDb.delete();

// then
assertEquals(0, derbyDb.contain(dateStr, word));
}


(You see on here,I used 'save' method. )

2-)

@Test
public void testDelete() throws SQLException {
// Given
String dateStr = "09-May-2016";
String word = "testWord";
PreparedStatement insertemp = conn
.prepareStatement("insert into " + tableName + "(PUBLISHDATE,WORD,FREQUENCY) values(?,?,?)");
insertemp.setString(1, dateStr);
insertemp.setString(2, word);
insertemp.setInt(3, frequency);
insertemp.executeUpdate();

// When
assertEquals(2, derbyDb.contain(dateStr, word));
derbyDb.delete();

// then
assertEquals(0, derbyDb.contain(dateStr, word));
}


Which one is true or better one?Or Should test unit be independent from other functions?

EDIT:AssertEquals added before delete.

EDIT-2:In second option,there should be just one method which is 'delete' and will be indepent from other methods in class.So instead of contain method there should be a query.

Answer

Assuming that you test the save method by itself too, I would use 1, in order that your delete tests don't break if you change the internal implementation of save to use some other mechanism.

Alternatively, you could do the insertion of the records to delete in a @Before method, in order that you simply have the delete in the actual test, to make it clear that it what is being tested in the method.

In either case, you should assertEquals(2, derbyDb.contain(dateStr, word)); before the delete, so you know that the delete is the reason why it is zero after.


Google's Testing on the Toilet blog has a post related to this: "Test Behavior, Not Implementation".

Tests that are independent of implementation details are easier to maintain since they don't need to be changed each time you make a change to the implementation. They're also easier to understand since they basically act as code samples that show all the different ways your class's methods can be used, so even someone who's not familiar with the implementation should usually be able to read through the tests to understand how to use the class.

Duplicating the database-level logic in the tests is testing implementation. You might need to make future changes like:

  • Renaming database tables and columns;
  • Changing the derbyDb class to use some other underlying storage - maybe you want an in-memory implementation of it, or something you can't connect to with JDBC.

If you've taken the second approach, you've got to go and fix the tests as well as the code under test.

If you've taken the first approach, you don't. Everything "just works" in the test - or it doesn't, but then you know it is a faulty implementation, not a faulty test.