Skip to content

Instantly share code, notes, and snippets.

@zverbatim
Created March 5, 2018 22:26
Show Gist options
  • Save zverbatim/6107416915da8926870960fa8095da64 to your computer and use it in GitHub Desktop.
Save zverbatim/6107416915da8926870960fa8095da64 to your computer and use it in GitHub Desktop.
@mock vs @InjectMock (mockito)
// Source: https://stackoverflow.com/questions/16467685/difference-between-mock-and-injectmocks
@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 that you must use @RunWith(MockitoJUnitRunner.class) or Mockito.initMocks(this) to initialise these mocks and inject them.
@RunWith(MockitoJUnitRunner.class)
public class SomeManagerTest {
@InjectMocks
private SomeManager someManager;
@Mock
private SomeDependency someDependency; // this will be injected into someManager
//tests...
}
-----------------------------------------------------------------------------------------------------------------------------
A more extenssive one using spy
I will show you 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>.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment