What is the difference between @Mock and @InjectMocks in Mockito framework?
We can use the @MockBean to add mock objects to the Spring application context. The mock will replace any existing bean of the same type in the application context. If no bean of the same type is defined, a new one will be added.
@Mock: It is used to mock the objects that helps in minimizing the repetitive mock objects. It makes the test code and verification error easier to read as parameter names (field names) are used to identify the mocks. The @Mock annotation is available in the org. mockito package.
Using the @Mock annotation – allows shorthand creation of objects required for testing. minimizes repetitive mock creation code. makes the test class more readable. makes the verification error easier to read because field name is used to identify the mock.
@InjectMocks is the Mockito Annotation. It allows you to mark a field on which an injection is to be performed. Injection allows you to, Enable shorthand mock and spy injections.
@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... }
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>.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With