I'll preface this with the background that I am very green and don't have much experience with testing in general, and have never used a mocking framework before.
I am writing unit tests for code that hits a lot of different web services, which I have mocked. Many of my tests verify the result of a call where all of my service calls are successful except a call to ServiceX. My first instinct was to set up happy-path behavior for all mocks in a @Before block and then modify the mock behavior for each test.
@Before
public void init(){
when(serviceA.doSomething()).thenReturn(true);
when(serviceB.doSomething()).thenReturn(true);
when(serviceC.doSomething()).thenReturn(true);
when(serviceD.doSomething()).thenReturn(true);
when(serviceE.doSomething()).thenReturn(true);
}
@Test
public void testDoBusinessSuccess(){
String result = businessLogic.doBusiness();
assertThat(result, is("success"));
}
@Test
public void testDoBusinessFailureWhenServiceAFails(){
when(serviceA.doSomething()).thenReturn(false);
String result = businessLogic.doBusiness();
assertThat(result, is("service A is down!"));
}
@Test
public void testDoBusinessFailureWhenServiceBFails(){
when(serviceB.doSomething()).thenReturn(false);
...
which makes each test case succinct, and it is easy to see what is being tested, since I only specify the behavior which deviates from the norm.
But I suspect that this is not how Mockito wants me to set up mock behaviors, because when I tried to verify that a failure in ServiceB means that ServiceC is never hit, I realized that my calls to when(serviceC.doSomething())
in the @Before counted as invocations on serviceC. That is, my verifyZeroInteractions(serviceC)
always failed because I had called when(serviceC.doSomething()).thenReturn(true)
, even when the test case never touched serviceC otherwise.
So what is the best practice? Am I better off just explicitly setting up the behavior for every mock in every test, even though I'd be repeating nearly the same 5 lines all over the place?