Inject Mock Objects as Method Parameters

  • Useful when multiple test methods need mock objects.
  • Saves some trivial mock object creation code.

Traditional mock creation:

class MyTest {

    void test() {
        MyObject myObjectMock = Mockito.mock(MyObject.class);
        ...
    }
}

With mock object injection in Junit 5:

@ExtendWith(MockitoExtension.class)
class MyTest {

    void test(@Mock MyObject myObjectMock) {
        ...
    }
}
  • @ExtendWith(MockitoExtension.class): Use the mockito Junit 5 extension
  • @Mock: Annotation for test method parameters. Injects a mock object.

Argument Matching with Hamcrest Matchers

See https://github.com/LeoNiedermeier/io.github.leoniedermeier.utils/blob/master/src/test/java/io/github/leoniedermeier/utils/test/mockito/MockitoHamcrestArgumentMatcherTest.java

Use the static methods of MockitoHamcrest for creating mockito ArgumentMatcher from a hamcrest Matcher

class MyService {
   public String someMethod(String string) { ... }
}

@Test
void hamcrestArgumentMatcher(@Mock MyService myService) {

    Mockito.when(myService.someMethod(MockitoHamcrest.argThat(Matchers.startsWith("ABC")))).thenReturn("123");
 
    String result = myService.someMethod("ABCDE");

    assertEquals("123", result);
    Mockito.verify(myService).someMethod(MockitoHamcrest.argThat(Matchers.startsWith("ABC")));
}

Mock with org.mockito.stubbing.Answer<T>

See https://github.com/LeoNiedermeier/io.github.leoniedermeier.utils/blob/master/src/test/java/io/github/leoniedermeier/utils/test/mockito/MockitoAnswerTest.java

The org.mockito.stubbing.Answer<T> can be implemented via:

  • inner class
  • lambda expression
  • method reference
  • AdditionalAnswers
class MyService {
    public String someMethod(String string) { ... }
}
@Test
void mockWithAnswer(@Mock MyService mock) {
    Mockito.when(mock.someMethod(ArgumentMatchers.anyString())).then(new Answer<String>() {
        @Override
        public String answer(InvocationOnMock invocation) {
            Object[] args = invocation.getArguments();
            return "Mock:" + args[0];
        }
    });
    assertEquals("Mock:foo", mock.someMethod("foo"));
}

@Test
void mockWithLambdaAnswer(@Mock MyService mock) {
    Mockito.when(mock.someMethod("foo"))
      .then(invocation -> {
        Object[] args = invocation.getArguments();
        return "Mock:" + args[0];
    });
    assertEquals("Mock:foo", mock.someMethod("foo"));
}
@Test
void mockWithMethodReferenceAnswer(@Mock MyService mock) {
    Mockito.when(mock.someMethod("foo")).then(this::answerMethod);
    assertEquals("Mock:foo", mock.someMethod("foo"));
}

private String answerMethod(InvocationOnMock invocation) {
    Object[] args = invocation.getArguments();
    return "Mock:" + args[0];
}

AdditionalAnswers provides factory method for Answers. In particular the an Answer can be created from functional interfaces which mimic the mocked method with respect to its parameters. No InvocationOnMock needed. Nice to combine with method references.

@Test
void mockWithAdditionalAnswers(@Mock MyService mock) {
    Mockito.when(mock.someMethod(ArgumentMatchers.anyString()))
    // or as Method reference... AdditionalAnswers.answer("Mock:"::concat)
    .then(AdditionalAnswers.answer((String s) -> "Mock:" + s));
    
    assertEquals("Mock:foo", mock.someMethod("foo"));
}

References