Mockito中的动态链接"thenReturn"

19

我有一个元组模拟类,期望会调用其getString(0)和getString(1)方法n次。不想写类似以下的代码:

when(tuple.getString(0)).thenReturn(logEntries[0]).thenReturn(logEntries[1])...thenReturn(logEntries[n - 1])

我手动尝试了以下方法:

OngoingStubbing stubbingGetStringZero = when(tuple.getString(0)).thenReturn(serviceRequestKey);
OngoingStubbing stubbingGetStringOne = when(tuple.getString(1)).thenReturn(logEntries[0]);
for (int i = 1; i < n; i++) {
    stubbingGetStringZero = stubbingGetStringZero.thenReturn(serviceRequestKey);
    stubbingGetStringOne = stubbingGetStringOne.thenReturn(logEntries[i]);
}
预期的结果是所有对 tuple.getString(0) 的调用都应该返回字符串 serviceRequestKey,而每个对 tuple.getString(1) 的调用都应该返回不同的字符串 logEntries[i],即第i次调用 tuple.getString(1) 返回logEntries数组的第i个元素。然而由于某些奇怪的原因,事情混淆了,第二次对 tuple.getString(1) 的调用返回字符串 serviceRequestKey,而不是 logEntries [1] 。我在这里漏掉了什么?
4个回答

23

好的,正确的做法是:

import org.mockito.AdditionalAnswers;

String[] logEntry = // Some initialization code
List<String> logEntryList = Arrays.asList(logEntry);
when(tuple.getString(1)).thenAnswer(AdditionalAnswers.returnsElementsOf(logEntryList));

在每次调用中,会返回logEntry数组的连续元素。因此,tuple.getString(1)的第i次调用将返回logEntry数组的第i个元素。
P.S:文档中returnsElementsOf的示例(截至本篇写作时)尚未更新(仍在使用ReturnsElementsOf示例):http://docs.mockito.googlecode.com/hg/1.9.5/org/mockito/AdditionalAnswers.html#returnsElementsOf(java.util.Collection)it

6
如果我理解得正确,您希望模拟返回不同的结果,具体取决于调用(当第一次调用时返回result1,第二次调用时返回result2等)-可以通过以下方式实现。
Mockito.when(tuple.getString(0)).thenReturn(serviceRequestKey,logEntries[0],logEntries[1])

使用这个方法,第一次调用将获得serviceRequestKey,第二次调用将获得logEntries[0]等等...

如果您需要更复杂的操作,例如根据方法中的参数更改返回值,请使用thenAnswer(),如此处所示。


嗯,你的答案是正确的,本质上是多个thenReturn的简写版本。唯一的问题是我的情况下调用次数有点多 ~ 15-20次左右。所以,我将不得不为每个thenReturn编写那么多参数。希望能找到使用for循环或其他方法的解决方案。 - gjain
然后返回方法接受String[],因此您可以在循环中按您想要的方式创建数组,然后将其传递。 - Nadir
thenReturn() 只接受多个 String 参数,而不是数组。请参阅:http://docs.mockito.googlecode.com/hg/org/mockito/stubbing/OngoingStubbing.html。无论如何,您的评论帮助我朝正确的方向查找。谢谢! - gjain
1
@gjain,可变参数只是数组的语法糖,因此String[]会很好地工作。请参见https://dev59.com/7HA85IYBdhLWcg3wJf4Z以获取更多详细信息。 - Mikael Ohlson
1
@MikaelOhlson 问题在于你需要花费很长时间来学习Mockito的语法,因为你需要从数组中剪切掉第一个参数以适应:thenReturn(T value, T... values),然后使用subList,这很麻烦。 - deworde

-1

我知道这篇文章比较旧了,但或许它能帮到你:

    OngoingStubbing<Boolean> whenCollectionHasNext = when(mockCollectionStream.hasNext());
    for (int i = 0; i < 2; i++) {
        whenCollectionHasNext = whenCollectionHasNext.thenReturn(true);
    }
    whenCollectionHasNext = whenCollectionHasNext.thenReturn(false);

这个不起作用。以下是错误信息:“您可能已经存储了由when()返回的OngoingStubbing的引用,并在此引用上多次调用了像thenReturn()这样的存根方法。” - Younes El Ouarti

-1

我不确定我是否足够理解Mockito来理解你的例子,但是你是否想要类似这样的东西:

Mockito.when(tuple.getString(0)).thenReturn(serviceRequestKey);
for(int i = 0;i < logEntries.length;i++) {
    Mockito.when(tuple.getString(i+1)).thenReturn(logEntries[i]);
}

我进一步澄清了问题。实际上,我希望每次调用tuple.getString(1)都能得到不同的结果。请注意,它始终是tuple.getString(1),索引不会改变。 - gjain

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接