是否有一种方法可以让存根方法在后续调用时返回不同的对象?我希望这样做是为了测试来自ExecutorCompletionService的不确定响应。也就是说,测试不管方法的返回顺序如何,结果都保持不变。
我要测试的代码看起来像这样。
// Create an completion service so we can group these tasks together
ExecutorCompletionService<T> completionService =
new ExecutorCompletionService<T>(service);
// Add all these tasks to the completion service
for (Callable<T> t : ts)
completionService.submit(request);
// As an when each call finished, add it to the response set.
for (int i = 0; i < calls.size(); i ++) {
try {
T t = completionService.take().get();
// do some stuff that I want to test
} catch (...) { }
}
Following可以用作一个通用方法,在不同的方法调用上返回不同的参数。我们需要做的唯一一件事是,我们需要传递一个数组,其中对象应该在每次调用中检索。
@SafeVarargs
public static <Mock> Answer<Mock> getAnswerForSubsequentCalls(final Mock... mockArr) {
return new Answer<Mock>() {
private int count=0, size=mockArr.length;
public Mock answer(InvocationOnMock invocation) throws throwable {
Mock mock = null;
for(; count<size && mock==null; count++){
mock = mockArr[count];
}
return mock;
}
}
}
示例:getAnswerForSubsequentCalls(mock1, mock3, mock2);在第一次调用时返回mock1对象,第二次调用时返回mock3对象,第三次调用时返回mock2对象。
应该像(something())那样使用。doAnswer(getAnswerForSubsequentCalls(mock1, mock3, mock2));
这几乎类似于when(something())。然后返回(mock1, mock3, mock2);
BDD风格:
import static org.mockito.BDDMockito.given;
...
given(yourMock.yourMethod()).willReturn(1, 2, 3);
经典的风格:
import static org.mockito.Mockito.when;
...
when(yourMock.yourMethod()).thenReturn(1, 2, 3);
明确的风格:
...
when(yourMock.yourMethod())
.thenReturn(1)
.thenReturn(2)
.thenReturn(3);
取决于参数
假设我们有2个参数,检查第2个(列表)参数的大小:
...
when(yourMock.yourMethod(any(), anyList()))
.thenAnswer(args -> ((List) args.getArgument(1)).size() < 2
? 1
: 3);
arg是对象,所以我们必须将arg转换为我们的类型。在我的例子中,我转换了^^^ to (List)。
BDD
...
given(yourMock.yourMethod(any(), anyList()))
.willAnswer(args -> ((List) args.getArgument(1)).size() < 2
? 1
: 3);
这可能是基本的/明显的,但如果像我一样,你试图模拟一个方法的多次调用,每次调用要测试的方法被调用未知次数,例如:
public String method(String testArg) {
//...
while(condition) {
someValue = someBean.nestedMethod(); // This is called unknown number of times
//...
}
//...
}
你可以这样做:
@Test
public void testMethod() {
mockNestedMethodForValue("value1");
assertEquals(method("arg"), "expected1");
mockNestedMethodForValue("value2");
assertEquals(method("arg"), "expected2");
mockNestedMethodForValue("value3");
assertEquals(method("arg"), "expected3");
}
private void mockNestedMethodForValue(String value) {
doReturn(value).when(someBeanMock).nestedMethod();
}