我很惊讶地发现以下简单代码示例不适用于所有> 1.8.5的Mockito版本
@RunWith(MockitoJUnitRunner.class)
public class MockitoTest {
@Mock(name = "b2")
private B b2;
@InjectMocks
private A a;
@Test
public void testInjection() throws Exception {
assertNotNull(a.b2); //fails
assertNull(a.b1); //also fails, because unexpectedly b2 mock gets injected here
}
static class A{
private B b1;
private B b2;
}
interface B{}
}
在javadocs(http://docs.mockito.googlecode.com/hg/latest/org/mockito/InjectMocks.html)中有一个引号:
注意1:如果您具有相同类型(或相同擦除)的字段,则最好用匹配的字段来命名所有@Mock注释的字段,否则Mockito可能会造成混淆,并且不会进行注入。
这是否意味着如果我有几个具有相同类型的字段,我就不能只模拟其中一个,而应该@Mock
为所有具有相同类型的字段定义?它是已知的限制吗,还有什么原因为什么还没有解决?@Mock
按字段名称匹配应该很简单,不是吗?
Mockito似乎使用了JavaDoc中描述的算法
如果我理解正确,它将首先对类型进行排序(在这种情况下仅为1 B),然后对名称进行排序(此处无更改)。最终它将使用OngoingInjector接口实现进行注入,该实现似乎是搜索第一个字段并将其注入。
由于您仅定义了1个B,并且在Mock中有2个B字段,因此它将看到第一个实例与该字段的匹配并停止。这是因为mocks.size() == 1
在NameBasedCandidateFilter中。因此它将停止过滤并直接注入。如果创建相同类型的多个模拟,它们将按Name排序并相应注入。
当创建特定类型的多个模拟(但少于字段数)时,我能够使它工作。
@RunWith(MockitoJUnitRunner.class)
public class MockitoTest {
@Mock(name = "b2")
private B b2;
@Mock(name = "b3")
private B b3;
@InjectMocks
private A a;
@Test
public void testInjection() {
System.out.println(this.a);
}
static class A {
private B b1;
private B b2;
private B b3;
}
interface B {
}
}
这将正确地将b2注入a.b2并将b3注入a.b3,而不是a.b1和a.b2(在A中定义的前两个字段)。
您可以随时将GitHub问题保留在其存储库中,以增强或更改注入过滤算法,以便进行查看。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句