为什么@InjectMocks
可能是这种测试需要避免的事情。
@RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
@Mock
private Bar bar;
@InjectMocks
private Foo foo; // created by Mockito
@Test
public void shouldCallMethod() {
// when
foo.myMethod();
// then
...
}
}
Foo.java
public class Foo {
private final Bar bar;
public Foo(Bar bar) {
this.bar = bar;
}
...
我在对这个答案的评论中读到了这一点:https://stackoverflow.com/a/21172873/516167
关于@InjectMocks
标记应在其上执行注入的字段。
- 允许简写mock和spy注入
- 最大限度地减少重复的模拟和间谍注入
参考:@InjectMocks JavaDoc。
我看到的唯一缺点是你必须遵守它的规则。如果你不使用@InjectMocks
,你可能会有更多的控制权
从他们的文档中,我在bold:中添加了一些
Mockito将尝试仅通过构造函数注入来注入mock,setter注入或属性注入在下面如果以下任何策略失败,则Mockito不会报告失败;即您必须自己提供依赖关系。
构造函数注入选择最大的构造函数,然后参数是通过仅在测试中声明的mock来解决的。注:如果找不到参数,则传递null。如果不可模拟类型则构造函数注入不会发生。在这些情况下,您必须自己满足依赖关系。
属性设置器注入;mock将首先按类型解析,如果存在多个相同类型的属性,则通过属性名称和模拟名称。注1:如果您具有相同类型(或相同擦除),最好命名所有@Mock带匹配属性的注释字段,否则Mockito可能弄糊涂了就不会打针了
注意2:如果@InjectMocks实例以前没有初始化,并且有没有arg构造函数,则将使用此构造函数对其进行初始化。
现场注入;mock将首先按类型解析,然后,如果存在根据字段名称的匹配,是同一类型的几个属性以及模拟名称。注1:如果您有相同类型的字段(或相同的擦除),最好使用匹配字段,否则Mockito可能会混淆并注入不会发生。
注意2:如果@InjectMocks实例以前没有初始化,并且有没有arg构造函数,则将使用此构造函数对其进行初始化。
此外,有些人建议应该通过构造函数而不是setter添加依赖项,这样可以在编译时保证正确的依赖项。看看这个。
通过使用构造函数,您被迫限制作为依赖项使用的组件数量,从而降低复杂性。(这可能并不容易,而且会改变春季的工作方式)。
更新:经过一段时间在构造函数中使用自动连接的依赖关系,我清楚地注意到测试不那么脆弱。当依赖关系发生变化时,我仍然需要更改测试,但编译器告诉我应该在哪里更改它以及更改的大小。更好的是,现在我可以区分在编译时为适应新代码而对测试进行的更改和运行时此代码添加的失败。