Difference between @Mock and @InjectMocks
mockito框架中的
请注意,必须使用
1 2 3 4 5 6 7 8 9 10 11 12 | @RunWith(MockitoJUnitRunner.class) public class SomeManagerTest { @InjectMocks private SomeManager someManager; @Mock private SomeDependency someDependency; // this will be injected into someManager //tests... } |
这是有关
假设我们有
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | 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; } } |
如您所见,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | @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将使用
注意,您甚至不必创建
1 2 | // you don't have to do this Game game = new Game(player); |
我们还将使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | @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将检查游戏类的
在您的测试类中,测试类应该用
1 2 | @InjectMocks private SomeManager someManager; |
从那时起,我们可以指定类中哪些特定的方法或对象将被mock替换,在这种情况下,
1 2 | @Mock private SomeDependency someDependency; |
在这个例子中,
两者都是互补的。
- @mock为您需要的类创建一个mock实现。
- @injectmock创建类的一个实例,并将用annotations@mock标记的mock注入其中。
例如
1 2 3 4 5 6 7 8 9 10 | @Mock StudentDao studentDao; @InjectMocks StudentService service; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); } |
这里我们需要服务类的DAO类。所以,我们模拟它并将其注入到服务类实例中。同样,在Spring框架中,所有@autowired bean都可以被@mock在JUnits中模拟,并通过@injectmocks注入到bean中。
这个链接有一个很好的mockito框架教程
mockito所基于的"mocking framework"是一个框架,它使您能够创建模拟对象(在旧术语中,这些对象可以称为分支,因为它们作为依赖功能的分支工作)。换句话说,模拟对象用于模拟代码所依赖的真实对象,您可以使用模拟框架创建代理对象。通过在测试中使用模拟对象,您基本上可以从普通的单元测试转向集成测试。
McCito是MIT许可下发布的一个Java开源测试框架,它是一个"嘲弄框架",它允许你用简洁简洁的API编写漂亮的测试。在Java空间中有许多不同的模拟框架,但是基本上有两种主要类型的模拟对象框架,它们是通过代理实现的,并且是通过类重新映射实现的。
依赖项注入框架(如Spring)允许您在不修改任何代码的情况下注入代理对象,模拟对象期望调用某个方法,它将返回预期的结果。
@tom所提到的方法的一个优点是,您不必在somemanager中创建任何构造函数,从而限制客户机实例化它。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | @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... } |
这是否是一个好的实践取决于您的应用程序设计。
许多人在这里对
示例参考:https://tedvinke.wordpress.com/2014/02/13/mockito-why-you-should-not-use-injectmocks-annotation-to-autowire-fields/
@InjectMocks注释可用于自动将模拟字段注入测试对象。
在下面的示例中,@injectmocks用于将模拟数据映射注入到数据库中。
1 2 3 4 5 6 7 8 9 10 11 12 13 | @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")); } |
例如:
1 2 3 4 5 6 7 8 9 | public class A{ public class B b; public void doSomething(){ } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | public class TestClassA{ @Mocks public class B b; @InjectMocks public class A a; @Test public testDoSomething(){ } } |
注意,EDOCX1[1]即将被否决
deprecate @InjectMocks and schedule for removal in Mockito 3/4
您可以通过@avp answer and link访问:
Why You Should Not Use InjectMocks Annotation to Autowire Fields