Hi,
This post is about unit testing. Writing tests, as you already know, is very important. The more important thing, as I learnt lately, is writing testable code. Writing testable code requires more intelligent designs and hard work. Also you must expect your workers or colleagues or boss might be get upset when you try to write or make them to write testable code, because it will take time. But think that way; you write your business logic in 3 days and writing tests on them takes 10 days. Not this only, you change your business logic whenever you get stuck on writing test, and worst you drop writing test at all. Am I exaggerating? No, I don’t think so. You must spend your time on your business logic, it will be responsible for work not tests. So, maybe you are asking yourselves that why I’m writing tests. In fact if you are here, then you know the importance of it. You can (and should) read from Miško Hevery‘s blog. He is fantastic and he has valuable thoughts on testing. I’m stopping talking about philosophy of testing and coming to action, read Miško Hevery, seriously.
The code I will share is about testing your code using JUnit and Mockito. I’ll not talk about JUnit, I’ll talk about Mockito a bit and show them to you in action in a dummy project.
You wrote your code, you are sure it will work. Your classes are full of intelligent decisions and designs. But at some point they are all dependent of others. Others depends on others etc. The meaning of unit test is testing units of your project in isolation. Class A depends on B and C but in TestA.java you should concentrate on only A. So you must find a way to simulate B and C in a way that they work perfectly. Mockito comes here to solve your problems. (Misko Hevery has some posts on dependencies in classes, they might help you at this point.) Create mocks(simulations) of your dependencies, provide them some functionality and let them go. You must test your units one by one in unit tests. You can read about Mockito here, and JUnit here.
Here is the class:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; public class DummyFileReader { public void readNames(String path) { InputStream resourceAsStream = DummyFileReader.class.getResourceAsStream(path); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(resourceAsStream)); String name; try { while ((name = bufferedReader.readLine()) != null) { System.out.println(name); } } catch (IOException e) { e.printStackTrace(); } } }
And here is the test class:
import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.doThrow; public class DummyFileReaderTest { @Mock DummyFileReader dummyFileReader; @Rule public ExpectedException expectedException = ExpectedException.none(); @Before public void setup() { MockitoAnnotations.initMocks(this); doThrow(new RuntimeException("Intended Exception")).when(dummyFileReader).readNames(anyString()); } @Test public void testReadNames() throws Exception { expectedException.expect(RuntimeException.class); expectedException.expectMessage("Intended Exception"); dummyFileReader.readNames("names"); } }
I have a class that has only one method “readNames” which has no return value. Mockito has a problem about void methods. If you don’t mock the method then they do nothing. If you mock them you have 2 options, doNothing and doThrow. I want to show you that you can use ExpectedException annotation to test your void methods with cooperation of Mockito and JUnit. Now you can test your mocks which have doThrow functionality using ExpectedException. You could use @Test(expected = MyException.class) but you have more control(eg. message of exception) over your tests now.
One point; Mockito.doThrow can only throw unchecked exceptions.
You can find the source code here.