在Mockito框架中@Mock和@InjectMocks之间有什么区别?


当前回答

很多人已经在这里给出了关于@Mock和@InjectMocks的很好的解释。我喜欢它,但我认为我们的测试和应用程序应该以这样一种方式编写,我们不应该使用@InjectMocks。

进一步阅读的示例参考:https://tedvinke.wordpress.com/2014/02/13/mockito-why-you-should-not-use-injectmocks-annotation-to-autowire-fields/

其他回答

很多人已经在这里给出了关于@Mock和@InjectMocks的很好的解释。我喜欢它,但我认为我们的测试和应用程序应该以这样一种方式编写,我们不应该使用@InjectMocks。

进一步阅读的示例参考:https://tedvinke.wordpress.com/2014/02/13/mockito-why-you-should-not-use-injectmocks-annotation-to-autowire-fields/

这是一个关于@Mock和@ injectmock如何工作的示例代码。

假设我们有Game和Player类。

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;
    }
}

如你所见,Game类需要玩家执行攻击。

@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将使用when and thenReturn方法模拟Player类及其行为。最后,使用@InjectMocks Mockito将该玩家放入游戏中。

注意,您甚至不需要创建一个新的Game对象。Mockito会给你注射的。

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

使用@Spy注释也会得到相同的行为。即使属性名不同。

@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();
  }

  // ...

这是因为Mockito将检查Game类的Type Signature,即Player和List<String>。

注意,@InjectMocks即将被弃用

弃用@InjectMocks并计划在Mockito 3/4中删除

你可以关注@avp的答案和链接:

为什么你不应该使用InjectMocks注释来自动装配字段

在您的测试类中,被测试的类应该使用@InjectMocks进行注释。这告诉Mockito将mock注入到哪个类中:

@InjectMocks
private SomeManager someManager;

从那时起,我们可以在类中指定特定的方法或对象,在这种情况下,SomeManager将被mock取代:

@Mock
private SomeDependency someDependency;

在这个例子中,SomeManager类中的SomeDependency将被模拟。

@Mock用于创建和注入模拟实例,而无需调用Mockito。手动模拟。在本例中,实例是ClassB。

而@InjectMocks用于自动将模拟字段注入到测试对象中。在这种情况下,它将是a类