802

What is the difference between @Mock and @InjectMocks in Mockito framework?

1

13 Answers 13

922

@Mock creates a mock. @InjectMocks creates an instance of the class and injects the mocks that are created with the @Mock (or @Spy) annotations into this instance.

Note you must use @RunWith(MockitoJUnitRunner.class) or Mockito.initMocks(this) to initialize these mocks and inject them (JUnit 4).

With JUnit 5, you must use @ExtendWith(MockitoExtension.class).

@RunWith(MockitoJUnitRunner.class) // JUnit 4 // @ExtendWith(MockitoExtension.class) for JUnit 5 public class SomeManagerTest { @InjectMocks private SomeManager someManager; @Mock private SomeDependency someDependency; // this will be injected into someManager // tests... } 
Sign up to request clarification or add additional context in comments.

10 Comments

Does this work for transitive dependencies or only direct members?
@PierreThibault Injecting mocks only works for direct members, but you can set a mock to allow deep stubs static.javadoc.io/org.mockito/mockito-core/3.0.0/org/mockito/…
i feel this is much clear than most of the article online.... that little comments save my ass...
I have some items that can not provided by @Mock annotation like context. How i can provide that for main class?
...and now Mockito.initMocks(this) is deprecated, Mockito.openMocks(this) should be used.
|
479

This is a sample code on how @Mock and @InjectMocks works.

Say we have Game and Player class.

class Game { private Player player; public Game(Player player) { this.player = player; } public String attack() { return "Player attack with: " + player.getWeapon(); } } class Player { private String weapon; public Player(String weapon) { this.weapon = weapon; } String getWeapon() { return weapon; } } 

As you see, Game class need Player to perform an attack.

@RunWith(MockitoJUnitRunner.class) class GameTest { @Mock Player player; @InjectMocks Game game; @Test public void attackWithSwordTest() throws Exception { Mockito.when(player.getWeapon()).thenReturn("Sword"); assertEquals("Player attack with: Sword", game.attack()); } } 

Mockito will mock a Player class and it's behaviour using when and thenReturn method. Lastly, using @InjectMocks Mockito will put that Player into Game.

Notice that you don't even have to create a new Game object. Mockito will inject it for you.

// you don't have to do this Game game = new Game(player); 

We will also get same behaviour using @Spy annotation. Even if the attribute name is different.

@RunWith(MockitoJUnitRunner.class) public class GameTest { @Mock Player player; @Spy List<String> enemies = new ArrayList<>(); @InjectMocks Game game; @Test public void attackWithSwordTest() throws Exception { Mockito.when(player.getWeapon()).thenReturn("Sword"); enemies.add("Dragon"); enemies.add("Orc"); assertEquals(2, game.numberOfEnemies()); assertEquals("Player attack with: Sword", game.attack()); } } class Game { private Player player; private List<String> opponents; public Game(Player player, List<String> opponents) { this.player = player; this.opponents = opponents; } public int numberOfEnemies() { return opponents.size(); } // ... 

That's because Mockito will check the Type Signature of Game class, which is Player and List<String>.

3 Comments

I sometimes find the testing with the mocking hard to understand and design for a class. However, this example helps a lot to provide the overview.
Probably too late to this thread but just in case someone sees this: What if the class I am doing an @Mock on itself has some dependencies that need to be injected? For example, say if the weapon was actually a class instead of a String?
@MarcoPolo - see this comment above
93

In your test class, the tested class should be annotated with @InjectMocks. This tells Mockito which class to inject mocks into:

@InjectMocks private SomeManager someManager; 

From then on, we can specify which specific methods or objects inside the class, in this case, SomeManager, will be substituted with mocks:

@Mock private SomeDependency someDependency; 

In this example, SomeDependency inside the SomeManager class will be mocked.

1 Comment

will this work if someManager has more then one constructor ? what if someManager had 5 constructors how would it know which one you want to use ?
77

@Mock annotation mocks the concerned object.

@InjectMocks annotation allows to inject into the underlying object the different (and relevant) mocks created by @Mock.

Both are complementary.

4 Comments

Can they be used in tandem on the same object?
Do you have a mini-example of your requirement?
I have a class that needs to be spied on (via Mockito Spy), and this class has a constructor. So I was thinking of using @InjectMocks to construct this class and spy on it too.
Is that what you're looking for? stackoverflow.com/a/35969166/985949
40
  • @Mock creates a mock implementation for the classes you need.
  • @InjectMock creates an instance of the class and injects the mocks that are marked with the annotations @Mock into it.

For example

@Mock StudentDao studentDao; @InjectMocks StudentService service; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); } 

Here we need the DAO class for the service class. So, we mock it and inject it in the service class instance. Similarly, in Spring framework all the @Autowired beans can be mocked by @Mock in jUnits and injected into your bean through @InjectMocks.

MockitoAnnotations.initMocks(this) method initialises these mocks and injects them for every test method so it needs to be called in the setUp() method.

This link has a good tutorial for Mockito framework

1 Comment

Thanks for the explanation. This is the first answer I read that made me understand a little better the difference between them.
20

enter image description here

@Mock is for creating and injecting mock instances without having to call Mockito.mock manually. In this example the instance would be ClassB.

Whereas, @InjectMocks is for injecting mock fields into the tested object automatically. In this case it would be ClassA

Comments

17

Though the above answers have covered, I have just tried to add minute detail s which i see missing. The reason behind them(The Why).

enter image description here


Illustration:

Sample.java --------------- public class Sample{ DependencyOne dependencyOne; DependencyTwo dependencyTwo; public SampleResponse methodOfSample(){ dependencyOne.methodOne(); dependencyTwo.methodTwo(); ... return sampleResponse; } } 

SampleTest.java ----------------------- @RunWith(PowerMockRunner.class) @PrepareForTest({ClassA.class}) public class SampleTest{ @InjectMocks Sample sample; @Mock DependencyOne dependencyOne; @Mock DependencyTwo dependencyTwo; @Before public void init() { MockitoAnnotations.initMocks(this); } public void sampleMethod1_Test(){ //Arrange the dependencies DependencyResponse dependencyOneResponse = Mock(sampleResponse.class); Mockito.doReturn(dependencyOneResponse).when(dependencyOne).methodOne(); DependencyResponse dependencyTwoResponse = Mock(sampleResponse.class); Mockito.doReturn(dependencyOneResponse).when(dependencyTwo).methodTwo(); //call the method to be tested SampleResponse sampleResponse = sample.methodOfSample() //Assert <assert the SampleResponse here> } } 

Reference

Comments

15

A "mocking framework", which Mockito is based on, is a framework that gives you the ability to create Mock objects ( in old terms these objects could be called shunts, as they work as shunts for dependend functionality ) In other words, a mock object is used to imitate the real object your code is dependend on, you create a proxy object with the mocking framework. By using mock objects in your tests you are essentially going from normal unit testing to integrational testing

Mockito is an open source testing framework for Java released under the MIT License, it is a "mocking framework", that lets you write beautiful tests with clean and simple API. There are many different mocking frameworks in the Java space, however there are essentially two main types of mock object frameworks, ones that are implemented via proxy and ones that are implemented via class remapping.

Dependency injection frameworks like Spring allow you to inject your proxy objects without modifying any code, the mock object expects a certain method to be called and it will return an expected result.

The @InjectMocks annotation tries to instantiate the testing object instance and injects fields annotated with @Mock or @Spy into private fields of the testing object.

MockitoAnnotations.initMocks(this) call, resets testing object and re-initializes mocks, so remember to have this at your @Before / @BeforeMethod annotation.

3 Comments

I would not say that "By using mock objects in your tests you are essentially going from normal unit testing to integrational testing". For me, mocking is to isolate the fixture to be tested in order to unit-test. Integration testing will use real not mocked dependencies.
@WesternGun I don't understand how your understanding of mocking is different from the part you quoted
Mocking is a typical UNIT testing procedure. Integration tests use the real dependencies. This is the plus to unit tests. It run in the real environment, not in an imitated special one to test one case.
11

One advantage you get with the approach mentioned by @Tom is that you don't have to create any constructors in the SomeManager, and hence limiting the clients to instantiate it.

@RunWith(MockitoJUnitRunner.class) public class SomeManagerTest { @InjectMocks private SomeManager someManager; @Mock private SomeDependency someDependency; // this will be injected into someManager //You don't need to instantiate the SomeManager with default contructor at all //SomeManager someManager = new SomeManager(); //Or SomeManager someManager = new SomeManager(someDependency); //tests... } 

Whether its a good practice or not depends on your application design.

2 Comments

what if someManager had 3 different constructors, how would it know which one to use ?
How do you then verify stuff on someManager if it is not mocked?
11

@Mock is used to declare/mock the references of the dependent beans, while @InjectMocks is used to mock the bean for which test is being created.

For example:

public class A{ public class B b; public void doSomething(){ } } 

test for class A:

public class TestClassA{ @Mocks public class B b; @InjectMocks public class A a; @Test public testDoSomething(){ } } 

Comments

11

@InjectMocks annotation can be used to inject mock fields into a test object automatically.

In below example @InjectMocks has used to inject the mock dataMap into the dataLibrary .

@Mock Map<String, String> dataMap ; @InjectMocks DataLibrary dataLibrary = new DataLibrary(); @Test public void whenUseInjectMocksAnnotation_() { Mockito.when(dataMap .get("aData")).thenReturn("aMeaning"); assertEquals("aMeaning", dataLibrary .getMeaning("aData")); } 

Comments

9

Many people have given a great explanation here about @Mock vs @InjectMocks. I like it, but I think our tests and application should be written in such a way that we shouldn't need to use @InjectMocks.

Reference for further reading with examples: https://tedvinke.wordpress.com/2014/02/13/mockito-why-you-should-not-use-injectmocks-annotation-to-autowire-fields/

1 Comment

This one seems to be a long term solution.
4

Notice that that @InjectMocks are about to be deprecated

deprecate @InjectMocks and schedule for removal in Mockito 3/4

and you can follow @avp answer and link on:

Why You Should Not Use InjectMocks Annotation to Autowire Fields

1 Comment

That "deprecation" issue was not implemented. Creator of mockito recommended against it.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.