Overview

Today, I will share with you three different ways to initialize mock objects in JUnit. Also, their advantage and inconvenience:

  • MockitoJUnitRunner
  • MockitoAnnotations#initMocks
  • Mockito#mock

I’m using JUnit 4 with Mockito 1.10.19.

MockitoJUnitRunner

Mock objects can be created using Mockito JUnit Runner (MockitoJUnitRunner). This runner is compatible with JUnit 4.4 and higher, this runner adds the following behavior:

  • Initializes mocks annotated with @Mock, so that explicit usage of MockitoAnnotations#initMocks(Object) is not necessary. Mocks are initialized before each test method.
  • Validates framework usage after each test method. See javadoc for Mockito#validateMockitoUsage()

Here’s an example of how you can use it:

@RunWith(MockitoJUnitRunner.class)
public class BookReaderAnnotationWithRunnerTest {

  @Mock
  private Book mockedBook;

  private BookReader reader;

  @Before
  public void setUp() {
    reader = new BookReader(mockedBook);
  }

  @Test
  public void testGetContent() {
    when(mockedBook.getContent()).thenReturn("Mockito");
    assertEquals("Mockito", reader.getContent());
  }
}

Pros:

  • Not need for explicit MockitoAnnotations#initMocks(Object)
  • Validates framework usage after each test method
  • Declarative thanks to @Mock annotation
  • Easy to read

Cons:

  • Annotation @RunWith can only be used once. This is not a repeatable annotation. Using @MockitoJUnitRunner means you cannot use other runners anymore.

MockitoAnnotations.initMocks

Mock objects can be initialized using Mockito annotation @Mock and MockitoAnnotations#initMocks(Object).

// no JUnit runner
public class BookReaderAnnotationWithSetupTest {

  @Mock
  private Book mockedBook;

  private BookReader reader;

  @Before
  public void setUp() {
    MockitoAnnotations.initMocks(this);
    reader = new BookReader(mockedBook);
  }

  @Test
  public void testGetContent() {
    when(mockedBook.getContent()).thenReturn("Mockito");
    assertEquals("Mockito", reader.getContent());
  }
}

Pros:

  • Declarative thanks to @Mock annotation
  • Easy to read

Cons:

  • Be careful about test-case inheritance

Mockito.mock

Create mock object of given class or interface using Mockito#mock(Class<T> classToMock) or its overloaded methods.

public class BookReaderClassicMockTest {

  private BookReader reader;
  private Book mockedBook;

  @Before
  public void setUp() {
    mockedBook = Mockito.mock(Book.class);
    reader = new BookReader(mockedBook);
  }

  @Test
  public void testGetContent() {
    when(mockedBook.getContent()).thenReturn("Mockito");
    assertEquals("Mockito", reader.getContent());
  }

Pros:

  • More control on the mock you need to create

Cons:

  • More verbose
  • Less declarative

Conclusion

Today, I share 3 different ways to initialize mock objects in JUnit, using Mockito JUnit Runner (MockitoJUnitRunner), Mockito Annations (MockitoAnnotation#initMocks), and the traditional Mockito#mock. The source code of the examples above are available on GitHub mincong-h/java-examples:

$ git clone https://github.com/mincong-h/java-examples.git --branch blog/2019-09-13-mock
$ cd java-examples
$ tree mock/src/test/java/io/mincongh/library/mockito/init
mock/src/test/java/io/mincongh/library/mockito/init
├── BookReaderAnnotationWithRunnerTest.java
├── BookReaderAnnotationWithSetupTest.java
└── BookReaderClassicMockTest.java

0 directories, 3 files

Hope you enjoy this article, see you the next time!

References