在Mockito框架中@Mock和@InjectMocks之间有什么区别?
当前回答
@Mock用于创建和注入模拟实例,而无需调用Mockito。手动模拟。在本例中,实例是ClassB。
而@InjectMocks用于自动将模拟字段注入到测试对象中。在这种情况下,它将是a类
其他回答
@Mock创建一个mock。@InjectMocks创建类的一个实例,并将使用@Mock(或@Spy)注释创建的模拟注入到该实例中。
注意,您必须使用@RunWith(MockitoJUnitRunner.class)或Mockito.initMocks(this)来初始化这些模拟并注入它们(JUnit 4)。
在JUnit 5中,必须使用@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...
}
这是一个关于@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>。
很多人已经在这里给出了关于@Mock和@InjectMocks的很好的解释。我喜欢它,但我认为我们的测试和应用程序应该以这样一种方式编写,我们不应该使用@InjectMocks。
进一步阅读的示例参考:https://tedvinke.wordpress.com/2014/02/13/mockito-why-you-should-not-use-injectmocks-annotation-to-autowire-fields/
@Mock用于声明/模拟依赖bean的引用,而@InjectMocks用于模拟正在为其创建测试的bean。
例如:
public class A{
public class B b;
public void doSomething(){
}
}
A类测试:
public class TestClassA{
@Mocks
public class B b;
@InjectMocks
public class A a;
@Test
public testDoSomething(){
}
}
使用@Tom提到的方法的一个好处是,您不必在SomeManager中创建任何构造函数,从而限制客户端实例化它。
@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...
}
这是否是一个好的实践取决于你的应用程序设计。
推荐文章
- 禁用IntelliJ星(包)导入?
- 面试问题:检查一个字符串是否是另一个字符串的旋转
- 将文件加载为InputStream的不同方法
- 如何使用Jest测试对象键和值是否相等?
- 到底是什么导致了堆栈溢出错误?
- 为什么Android工作室说“等待调试器”如果我不调试?
- Java:路径vs文件
- ExecutorService,如何等待所有任务完成
- Maven依赖Servlet 3.0 API?
- 如何在IntelliJ IDEA中添加目录到应用程序运行概要文件中的类路径?
- getter和setter是糟糕的设计吗?相互矛盾的建议
- Android room persistent: AppDatabase_Impl不存在
- Java的String[]在Kotlin中等价于什么?
- Intellij IDEA上的System.out.println()快捷方式
- 使用Spring RestTemplate获取JSON对象列表