173

There are many ways to initialize a mock object using MockIto. What is best way among these ?

1.

 public class SampleBaseTestCase {

   @Before public void initMocks() {
       MockitoAnnotations.initMocks(this);
   }
@RunWith(MockitoJUnitRunner.class)
mock(XXX.class);

suggest me if there are any other ways better than these...

knittl
  • 246,190
  • 53
  • 318
  • 364
Vinay Veluri
  • 6,671
  • 5
  • 32
  • 56

8 Answers8

187

For the mocks initialization, using the runner or the MockitoAnnotations.initMocks are strictly equivalent solutions. From the javadoc of the MockitoJUnitRunner :

JUnit 4.5 runner initializes mocks annotated with Mock, so that explicit usage of MockitoAnnotations.initMocks(Object) is not necessary. Mocks are initialized before each test method.


The first solution (with the MockitoAnnotations.initMocks) could be used when you have already configured a specific runner (SpringJUnit4ClassRunner for example) on your test case.

The second solution (with the MockitoJUnitRunner) is the more classic and my favorite. The code is simpler. Using a runner provides the great advantage of automatic validation of framework usage (described by @David Wallace in this answer).

Both solutions allows to share the mocks (and spies) between the test methods. Coupled with the @InjectMocks, they allow to write unit tests very quickly. The boilerplate mocking code is reduced, the tests are easier to read. For example:

@RunWith(MockitoJUnitRunner.class)
public class ArticleManagerTest {

    @Mock private ArticleCalculator calculator;
    @Mock(name = "database") private ArticleDatabase dbMock;
    @Spy private UserProvider userProvider = new ConsumerUserProvider();

    @InjectMocks private ArticleManager manager;

    @Test public void shouldDoSomething() {
        manager.initiateArticle();
        verify(database).addListener(any(ArticleListener.class));
    }

    @Test public void shouldDoSomethingElse() {
        manager.finishArticle();
        verify(database).removeListener(any(ArticleListener.class));
    }
}

Pros: The code is minimal

Cons: Black magic. IMO it is mainly due to the @InjectMocks annotation. With this annotation "you loose the pain of code" (see the great comments of @Brice)


The third solution is to create your mock on each test method. It allow as explained by @mlk in its answer to have "self contained test".

public class ArticleManagerTest {

    @Test public void shouldDoSomething() {
        // given
        ArticleCalculator calculator = mock(ArticleCalculator.class);
        ArticleDatabase database = mock(ArticleDatabase.class);
        UserProvider userProvider = spy(new ConsumerUserProvider());
        ArticleManager manager = new ArticleManager(calculator, 
                                                    userProvider, 
                                                    database);

        // when 
        manager.initiateArticle();

        // then 
        verify(database).addListener(any(ArticleListener.class));
    }

    @Test public void shouldDoSomethingElse() {
        // given
        ArticleCalculator calculator = mock(ArticleCalculator.class);
        ArticleDatabase database = mock(ArticleDatabase.class);
        UserProvider userProvider = spy(new ConsumerUserProvider());
        ArticleManager manager = new ArticleManager(calculator, 
                                                    userProvider, 
                                                    database);

        // when 
        manager.finishArticle();

        // then
        verify(database).removeListener(any(ArticleListener.class));
    }
}

Pros: You clearly demonstrate how your api works (BDD...)

Cons: there is more boilerplate code. (The mocks creation)


My recommandation is a compromise. Use the @Mock annotation with the @RunWith(MockitoJUnitRunner.class), but do not use the @InjectMocks :

@RunWith(MockitoJUnitRunner.class)
public class ArticleManagerTest {

    @Mock private ArticleCalculator calculator;
    @Mock private ArticleDatabase database;
    @Spy private UserProvider userProvider = new ConsumerUserProvider();

    @Test public void shouldDoSomething() {
        // given
        ArticleManager manager = new ArticleManager(calculator, 
                                                    userProvider, 
                                                    database);

        // when 
        manager.initiateArticle();

        // then 
        verify(database).addListener(any(ArticleListener.class));
    }

    @Test public void shouldDoSomethingElse() {
        // given
        ArticleManager manager = new ArticleManager(calculator, 
                                                    userProvider, 
                                                    database);

        // when 
        manager.finishArticle();

        // then 
        verify(database).removeListener(any(ArticleListener.class));
    }
}

Pros: You clearly demonstrate how your api works (How my ArticleManager is instantiated). No boilerplate code.

Cons: The test is not self contained, less pain of code

Skillz
  • 308
  • 4
  • 10
gontard
  • 28,720
  • 11
  • 94
  • 117
  • Be careful though, the annotations are useful but they don't protect you against to craft poor OO design (or to degrade it). Personally while I'm happy to reduce boilerplate code, I loose the pain of code (or PITA) that is the trigger to change the design to a better one, so I and the team are paying attention to OO design. I feel that following OO design with principles like SOLID design or the GOOS ideas is much more important that choosing how to instantiate mocks. – bric3 Mar 19 '13 at 10:06
  • @Brice why ? if the class under test (`ArticleManager`) have too much dependencies, i will clearly see it. And this is off the subject, the question is just about "how to instantiate mocks ?" – gontard Mar 19 '13 at 10:07
  • I should have said "less obvious" :) So actually @injectMocks will try it's best to inject mocks automatically without the user having to wire things (like we are used to do in spring or guice), so the object instantiation is hidden, you don't know if it's constructor injection or setter injection, that could be bothersome for the future usage of this object (reusability is one of the main benefit of good OO design). – bric3 Mar 19 '13 at 10:50
  • 1
    (follow up) If you don't see how this object is created you don't feel the pain about it, and future programmers might not react well if new functionality should be added. Anyway that is arguable both ways, I'm just saying to be careful about it. – bric3 Mar 19 '13 at 10:51
  • I am agree with you. I like the PITA idea. And thanks, i didn't know GOOS, it seems very interresting. Personnaly in my company, we use only constructor injection (no public setter | immutable object), so when i use `InjectMocks`, i really understand what it does. Although, i prefer the way described by @mlk in its answer (self contained tests). – gontard Mar 19 '13 at 10:59
  • @Brice I agree with your comment, – Vinay Veluri Mar 19 '13 at 12:47
  • @Gontard, I understood the latter one more clear, bottom line is to make test case more understandable, is that what it mean ? – Vinay Veluri Mar 19 '13 at 12:49
  • 8
    It is NOT CORRECT that these two are equivalent. It is NOT TRUE that simpler code is the only advantage to using `MockitoJUnitRunner`. For more information about the differences, see the question at http://stackoverflow.com/questions/10806345/runwithmockitojunitrunner-class-vs-mockitoannotations-initmocksthis/10812752#10812752 and my answer to it. – Dawood ibn Kareem Mar 19 '13 at 13:02
  • @DavidWallace i correct my answer. Thanks for noticing it. And i learn something too :) Feel free to edit and improve my answer. – gontard Mar 19 '13 at 13:54
  • @gontard Even using constructor injection could become wrong. `@InjectMocks` isn't picky and try to choose the best matching, so it depends on the number of dependencies, and the constructors code anyway, but again the coder might not feel the experience of instantiating and wiring these collaborators. And might miss an opportunity to use other approaches like a builder approach (the Joshua Bloch ones) or using providers (same as guava's suppliers). – bric3 Mar 19 '13 at 15:09
  • IMHO the number of dependencies is clearly visible in the test. And the purpose of a unit test is to test a class not its builder. – gontard Mar 19 '13 at 15:14
  • 2
    @Gontard Yeah sure dependencies are visible, but I've seen code gone wrong using this approach. About using the `Collaborator collab = mock(Collaborator.class)`, in my opinion this way is certainly a valid approach. While this might tend to be verbose, you can gain in understandability and refactorability of the tests. Both ways have their pros and cons, I've not yet decided which approach is better. Amyway it's always possible to write crap, and probably depends on the context and the coder. – bric3 Mar 19 '13 at 15:15
  • @DavidWallace a valid point in your answer. what about the third one ? is that method suggested ? – Vinay Veluri Mar 20 '13 at 06:45
  • @gontard On the point as to what unit tests are for: I disagree, the point of a test (in TDD) is to aid in the design of the class. It also gives quick feedback on if the class works as expected true, and a very good reason to write tests, but not the (only) reason for doing them. – Michael Lloyd Lee mlk Mar 20 '13 at 09:43
  • 1
    @mlk i am totally agree with you. My english is not very good and it lacks nuances. My point was to insist on the UNIT word. – gontard Mar 20 '13 at 09:50
  • In Junit5 there is the option of using [extension model](https://blog.codefx.org/design/architecture/junit-5-extension-model/). As described in [answer](https://stackoverflow.com/questions/40961057/how-to-use-mockito-with-junit5) – George Kargakis Jul 31 '20 at 14:26
33

There is now (as of v1.10.7) a fourth way to instantiate mocks, which is using a JUnit4 rule called MockitoRule.

@RunWith(JUnit4.class)   // or a different runner of your choice
public class YourTest
  @Rule public MockitoRule rule = MockitoJUnit.rule();
  @Mock public YourMock yourMock;

  @Test public void yourTestMethod() { /* ... */ }
}

JUnit looks for subclasses of TestRule annotated with @Rule, and uses them to wrap the test Statements that the Runner provides. The upshot of this is that you can extract @Before methods, @After methods, and even try...catch wrappers into rules. You can even interact with these from within your test, the way that ExpectedException does.

MockitoRule behaves almost exactly like MockitoJUnitRunner, except that you can use any other runner, such as Parameterized (which allows your test constructors to take arguments so your tests can be run multiple times), or Robolectric's test runner (so its classloader can provide Java replacements for Android native classes). This makes it strictly more flexible to use in recent JUnit and Mockito versions.

In summary:

  • Mockito.mock(): Direct invocation with no annotation support or usage validation.
  • MockitoAnnotations.initMocks(this): Annotation support, no usage validation.
  • MockitoJUnitRunner: Annotation support and usage validation, but you must use that runner.
  • MockitoRule: Annotation support and usage validation with any JUnit runner.

See also: How JUnit @Rule works?

Community
  • 1
  • 1
Jeff Bowman
  • 90,959
  • 16
  • 217
  • 251
  • 4
    In Kotlin, the rule looks like this: `@get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule()` – Cristan Mar 14 '18 at 11:51
29

1. Using MockitoAnnotations.openMocks():

The MockitoAnnotations.initMock() method in Mockito 2 is deprecated and replaced with MockitoAnnotations.openMocks() in Mockito 3. The MockitoAnnotations.openMocks() method returns an instance of AutoClosable which can be used to close the resource after the test. Below is an example using MockitoAnnotations.openMocks().

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;


class MyTestClass {

    AutoCloseable openMocks;

    @BeforeEach
    void setUp() {
        openMocks = MockitoAnnotations.openMocks(this);
        // my setup code...
    }

    @Test
    void myTest() {
        // my test code...
        
    }

    @AfterEach
    void tearDown() throws Exception {
        // my tear down code...
        openMocks.close();
    }

}

2. Using @ExtendWith(MockitoExtension.class):

As of JUnit5 @RunWith has been removed. Below is an example using @ExtendWith:

@ExtendWith(MockitoExtension.class)
class MyTestClass {

    @BeforeEach
    void setUp() {
        // my setup code...
    }

    @Test
    void myTest() {
        // my test code...

    }

    @AfterEach
    void tearDown() throws Exception {
        // my tear down code...
    }

}
Thanthu
  • 4,399
  • 34
  • 43
  • I am converting code that uses JUnit4 and Mockito 2 to Jupiter and Mockito 3. Thank you for this up-to-date answer! Updating `MockitoAnnotations.initMocks(this);` to example 1 worked great. Most of the other answers are now obsolete. – Phil Freihofner Mar 15 '22 at 17:20
  • 2
    Actually it has been deprecated in [Mockito 3.4.0](https://www.javadoc.io/doc/org.mockito/mockito-core/3.4.0/org/mockito/MockitoAnnotations.html), not in Mockito 3. You won't find `openMocks` method in [Mockito 3.3.0](https://www.javadoc.io/doc/org.mockito/mockito-core/3.3.0/org/mockito/MockitoAnnotations.html) – gmanjon May 10 '22 at 07:56
13

A little example for JUnit 5 Jupiter, the "RunWith" was removed you now need to use the Extensions using the "@ExtendWith" Annotation.

@ExtendWith(MockitoExtension.class)
class FooTest {

  @InjectMocks
  ClassUnderTest test = new ClassUnderTest();

  @Spy
  SomeInject bla = new SomeInject();
}
fl0w
  • 3,593
  • 30
  • 34
12

MockitoAnnotations & the runner have been well discussed above, so I'm going to throw in my tuppence for the unloved:

XXX mockedXxx = mock(XXX.class);

I use this because I find it a little bit more descriptive and I prefer (not out right ban) unit tests not to use member variables as I like my tests to be (as much as they can be) self contained.

Michael Lloyd Lee mlk
  • 14,561
  • 3
  • 44
  • 81
  • Is there any other advantage over using mock(XX.class) except making the test case to be self contained ? – Vinay Veluri Mar 19 '13 at 12:43
  • 4
    Less magic to have to understand in order to read the test. You declare the variable, and give it a value - no annotations, reflection etc. – Karu Jun 02 '15 at 04:14
11

There is a neat way of doing this.

  • If it's an Unit Test you can do this:

    @RunWith(MockitoJUnitRunner.class)
    public class MyUnitTest {
    
        @Mock
        private MyFirstMock myFirstMock;
    
        @Mock
        private MySecondMock mySecondMock;
    
        @Spy
        private MySpiedClass mySpiedClass = new MySpiedClass();
    
        // It's gonna inject the 2 mocks and the spied object per reflection to this object
        // The java doc of @InjectMocks explains it really well how and when it does the injection
        @InjectMocks
        private MyClassToTest myClassToTest;
    
        @Test
        public void testSomething() {
        }
    }
    
  • EDIT: If it's an Integration test you can do this(not intended to be used that way with Spring. Just showcase that you can initialize mocks with diferent Runners):

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("aplicationContext.xml")
    public class MyIntegrationTest {
    
        @Mock
        private MyFirstMock myFirstMock;
    
        @Mock
        private MySecondMock mySecondMock;
    
        @Spy
        private MySpiedClass mySpiedClass = new MySpiedClass();
    
        // It's gonna inject the 2 mocks and the spied object per reflection to this object
        // The java doc of @InjectMocks explains it really well how and when it does the injection
        @InjectMocks
        private MyClassToTest myClassToTest;
    
        @Before
        public void setUp() throws Exception {
              MockitoAnnotations.initMocks(this);
        }
    
        @Test
        public void testSomething() {
        }
    }
    
emd
  • 740
  • 4
  • 12
  • 1
    If MOCK is involved in Integration tests also, will it makes sense ? – Vinay Veluri Mar 19 '13 at 12:42
  • 2
    actually it won't, your right. I just wanted to show to possibilities of Mockito. For instance if your use RESTFuse you have to user their runner so you can initialize mocks with MockitoAnnotations.initMocks(this); – emd Mar 19 '13 at 12:48
7

In te lastest version of Mockito the method MockitoAnnotations.initMocks is deprecated

Preferred way is use

If you can not use dedicated runner/extension you can use MockitoSession

Slawomir Jaranowski
  • 7,381
  • 3
  • 25
  • 33
2

The other answers are great and contain more detail if you want/need them.
In addition to those, I would like to add a TL;DR:

  1. Prefer to use
    • @RunWith(MockitoJUnitRunner.class)
  2. If you cannot (because you already use a different runner), prefer to use
    • @Rule public MockitoRule rule = MockitoJUnit.rule();
  3. Similar to (2), but you should not use this anymore:
    • @Before public void initMocks() { MockitoAnnotations.initMocks(this); }
  4. If you want to use a mock in just one of the tests and don't want to expose it to other tests in the same test class, use
    • X x = mock(X.class)

(1) and (2) and (3) are mutually exclusive.
(4) can be used in combination with the others.

neXus
  • 2,005
  • 3
  • 29
  • 53