Java 为什么Mockito@InjectMocks可能是一件需要避免的事情?
为什么Java 为什么Mockito@InjectMocks可能是一件需要避免的事情?,java,unit-testing,dependency-injection,mockito,Java,Unit Testing,Dependency Injection,Mockito,为什么@InjectMocks可能是这种测试要避免的一件事 @RunWith(MockitoJUnitRunner.class) public class MyClassTest { @Mock private Bar bar; @InjectMocks private Foo foo; // created by Mockito @Test public void shouldCallMethod() { // when
@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
我在对这个答案的评论中读到了这一点:
关于@mock
标记应在其上执行注射的字段
- 允许速记模拟和间谍注入
- 最大限度地减少重复模拟和间谍注射
参考文献:JavaDoc。我看到的唯一缺点是您必须遵守其规则。 如果不使用
@InjectMocks
从他们的文档中,我添加了一些粗体字:
Mockito将尝试通过构造函数注入或,
按顺序和所述进行setter注入或属性注入
在下面如果以下任何策略失败,Mockito将不会
报告故障;i、 e.您必须自己提供依赖项
构造器注入选择最大的构造函数,然后
参数仅使用测试中声明的模拟进行解析。注:如果
找不到参数,则传递null。如果是不可模仿的类型
如果需要,则不会发生构造函数注入。在这些情况下,
您必须自己满足依赖关系
属性设置器注入;模拟将首先按类型解析,然后,
如果存在多个相同类型的属性,则
属性名和模拟名。注1:如果您具有
相同的类型(或相同的擦除),最好将所有名称命名为@Mock
带有匹配属性的注释字段,否则Mockito可能会
弄糊涂了,注射就不会发生。
注意2:如果@InjectMocks实例之前没有初始化,并且具有
没有参数构造函数,则将使用此构造函数初始化它
现场注入;mock将首先按类型解析,然后,如果有
根据字段名的匹配,是同一类型的多个属性
还有假名字。注1:如果您有相同类型的字段(或
相同的擦除),最好将所有@Mock注释字段命名为
匹配字段,否则Mockito可能会混淆和注入
不会发生的
注意2:如果@InjectMocks实例之前没有初始化,并且具有
没有参数构造函数,则将使用此构造函数初始化它
此外,有些人建议依赖项应该由构造函数而不是由setter添加,这样可以在编译时保证正确的依赖项。看 通过使用构造函数,您必须限制要用作依赖项的组件的数量,以降低复杂性。(这可能不容易,而且在春天会改变很多事情的方式)
更新:在使用构造函数中自动连接的依赖项一段时间后,我清楚地注意到测试不那么脆弱。当依赖项改变时,我仍然需要改变测试,但是编译器告诉我应该在哪里改变它,以及改变有多大。更好的是,现在我可以区分为适应编译时的新代码而对测试所做的更改和该代码在运行时添加的失败 我刚刚发现了
@InjectMocks
所发挥的魔力,这让我很烦恼。测试没有以任何方式标记为依赖于Spring,但依赖关系自动得到了满足。我不知道怎么做,所以试图弄清楚我需要为一个新的测试编写什么代码是令人困惑的。正如一篇文章所说——自己注入依赖项,不要让它成为不明显的不可见逻辑。
public class Foo {
private final Bar bar;
public Foo(Bar bar) {
this.bar = bar;
}
...