我只是对此感到困惑(Mockito 1.10):
@Rule
public MockitoRule rule = MockitoJUnit.rule();
@Mock
private Collection<IndexableField> mockedFieldsFromRetrievedDocument;
@Spy
@InjectMocks
private IndexManager injectedSpyIM = new IndexManager();
@Test
public void numberOfLDocsShouldBePrintedOutWithEachHitLine() throws Exception{
LOGGER.info( String.format( "# A: %d", mockedFieldsFromRetrievedDocument.hashCode() ));
LOGGER.info( String.format( "# fFRD %s", injectedSpyIM.getFFRD() ));
自然地,IndexManager
中有一种方法getFFRD
返回私有字段
private Collection<IndexableField> fieldsFromRetrievedDocument;
IndexManager
中还有另一个私人字段:
private Collection<Closeable> closeableComponents;
第一条记录线为您提供有效的障碍。
最后一行说
#ffrd null
然后,当我去检查closeableComponents
的值时,我发现它的哈希码确实是注射的模拟Collection
。
IndexManager
中交换这些字段的声明的位置:无更改。
看来,这里的@Mock
行是1)完全忽略了通用类,而2)由于我不了解的原因而不是另一个锁定的Collection<Closeable>
。
哇,疯狂的东西:我只是将字段closeableComponents
的名称更改为xcloseableComponents
。现在,模拟的领域确实在做我想做的事,即嘲笑字段fieldsFromRetrievedDocument
。
自然而然地,我的临时结论是,Mockito使用了Collection<anything>
类型的第一个字段名称……按字母顺序排列!大概相同的选择过程适用于其他"相同"类型的一个以上字段的其他情况。只是在没有成功的情况下对此进行了搜索:有人知道是否在某个地方记录了这一点?
后来仍然
按照杰夫·鲍曼(Jeff Bowman)的建议,我更改了类似的事情:
@Mock(name="fieldsFromRetrievedDocument")
private Collection<?> mockedFieldsFromRetrievedDocument;
...这是班级中字段的确切拼写。但是它仍然将错误的Collection<?>
注射为模拟。然后...
我从Mockito 1.10更改为最新的2.3.0:解决问题!一个警示性的故事,因为name
属性已在1.10的Javadoc API中完全记录下来...!
@InjectMocks
文档描述了这种行为,这可能比您喜欢的文献或确定性较低:
属性设置器注入;模拟将首先通过类型解决(如果单个类型的匹配注入将无论名称如何),那么,如果有几种类型的属性,则通过属性名称和模拟名称的匹配。
注意1:如果您具有具有相同类型(或相同擦除)的属性,则最好将所有@mock注释的字段命名为具有匹配属性发生。
这是一定有意义的,因为该字段的通用类型被删除(在运行时不可读取),并且因为Java的反射方法getDeclaredFields
和getDeclaredMethods
返回了"任何特定顺序"。匹配名称是首选的,其他一切都是未定义的行为,您的重命名偶然会为您的优势操纵;不要指望这种行为。
命名模拟的概念是指在@Mock
注释上使用name
属性。