Mockito - 什么规则管理类似Collection类的模拟注入?

时间:2016-12-10 19:31:43

标签: java dependency-injection mocking mockito

我对此感到困惑(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() ));

当然,getFFRD中的方法IndexManager会返回私有字段

private Collection<IndexableField> fieldsFromRetrievedDocument;

IndexManager中还有另一个私有字段:

private Collection<Closeable> closeableComponents;

第一个记录的行为您提供有效的哈希码。
最后一行显示

  

#fFRD null

当我去检查closeableComponents的值时,我发现它的哈希码确实是注入的模拟Collection的哈希码。

然后我尝试在IndexManager中交换这些字段的声明位置:没有变化。

这里的@Mock行似乎是1)完全忽略了通用类,2)因为我不明白的原因而优先于Collection<Closeable>锁定closeableComponents

稍后

哇,疯狂的东西:我刚刚将字段xcloseableComponents的名称更改为fieldsFromRetrievedDocument。现在,模拟的领域确实在做我想要的,即模仿领域Collection<anything>

我的临时结论自然就是Mockito按字母顺序使用它找到的@Mock(name="fieldsFromRetrievedDocument") private Collection<?> mockedFieldsFromRetrievedDocument; 类型的第一个字段名称!据推测,相同的选择过程适用于其他情况,其中有相同的&#34;相同的&#34;类型。只是用Google搜索没有成功:有人知道这是否记录在某处?

以后仍然

根据杰夫鲍曼的建议,我改变了这样的事情:

Collection<?>

...这是类中字段的确切拼写,正确的情况。但它仍然在注入错误的name作为模拟。然后......

我从Mockito 1.10变为最新的2.3.0:问题解决了!一个警示故事,<!DOCTYPE html> <!--Website made by William Stinson, 2016, Unsolicitedly.--> <html> <head> <style> .center { text-align: center; } </style> </head> <body> <div class="center"> <a href="http://www.gifford.org"> <img src="http://www.myhopesanddreams.com/william/giffordlogo.png" draggable="false" alt="logo" /> </a> <br> <img src="myhopesanddreams.com/Untitled 3.png" height="100" draggable="false"> <iframe src="https://docs.google.com/a/gifford.org/forms/d/e/1FAIpQLSeAojv3USFoCWLpHJeIoSEiOydke0dKV3wmS-EWrr4-qbxryw/viewform?embedded=true" width="1300" height="1000" frameborder="3" marginheight="0" marginwidth="0">Loading...</iframe> <h1>Created for The Gifford School by William Stinson</h1> </div> </body> </html>属性完全记录在1.10的Javadoc API中......!

1 个答案:

答案 0 :(得分:2)

@InjectMocks documentation描述的行为可能没有您喜欢的记录或确定性:

  

Property setter injection ; mocks将首先按类型解析(如果单个类型匹配注入将发生,无论名称如何),那么,如果有多个相同类型的属性,则通过匹配属性名称和模拟名称。

     

注意1:如果您拥有相同类型(或相同的删除)的属性,最好使用匹配的属性命名所有@Mock带注释的字段,否则Mockito可能会感到困惑注射不会发生。

这是有道理的,因为字段的泛型类型被删除 - 在运行时不可读 - 并且因为Java的反射方法getDeclaredFieldsgetDeclaredMethods被返回{{3 }}。匹配名称是首选,其他一切都是未定义的行为,您的重命名恰好操纵您的优势;不要指望这种行为。

上面命名模拟的概念是指在"not in any particular order"上使用name属性。