有没有办法让stubbed方法在后续调用中返回不同的对象?我想这样做来测试来自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 (...) { }
}
答案 0 :(得分:524)
怎么样
when( method-call ).thenReturn( value1, value2, value3 );
您可以在thenReturn的括号中添加任意数量的参数,前提是它们都是正确的类型。第一次调用方法时将返回第一个值,然后是第二个答案,依此类推。所有其他值用完后,将重复返回最后一个值。
答案 1 :(得分:200)
您可以使用thenAnswer
方法执行此操作(与when
链接时):
when(someMock.someMethod()).thenAnswer(new Answer() {
private int count = 0;
public Object answer(InvocationOnMock invocation) {
if (count++ == 1)
return 1;
return 2;
}
});
或使用等效的静态doAnswer
方法:
doAnswer(new Answer() {
private int count = 0;
public Object answer(InvocationOnMock invocation) {
if (count++ == 1)
return 1;
return 2;
}
}).when(someMock).someMethod();
答案 2 :(得分:103)
作为previously pointed out几乎所有的电话都是可链接的。
所以你可以打电话给
when(mock.method()).thenReturn(foo).thenReturn(bar).thenThrow(new Exception("test"));
//OR if you're mocking a void method and/or using spy instead of mock
doReturn(foo).doReturn(bar).doThrow(new Exception("Test").when(mock).method();
Mockito's Documenation中的更多信息。
答案 3 :(得分:60)
您甚至可以像这样链接doReturn()
方法调用
doReturn(null).doReturn(anotherInstance).when(mock).method();
可爱不是它:)。
答案 4 :(得分:4)
我已经实现了一个MultipleAnswer
课程,可以帮助我在每次通话中找到不同的答案。这段代码:
private final class MultipleAnswer<T> implements Answer<T> {
private final ArrayList<Answer<T>> mAnswers;
MultipleAnswer(Answer<T>... answer) {
mAnswers = new ArrayList<>();
mAnswers.addAll(Arrays.asList(answer));
}
@Override
public T answer(InvocationOnMock invocation) throws Throwable {
return mAnswers.remove(0).answer(invocation);
}
}
答案 5 :(得分:3)
doReturn(value1,value2,value3).when(方法调用)
答案 6 :(得分:1)
以下可以用作在不同方法调用上返回不同参数的常用方法。我们唯一需要做的就是我们需要传递一个数组,其中包含在每次调用中应该检索对象的顺序。
@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对象。
应该像when(something()).doAnswer(getAnswerForSubsequentCalls(mock1, mock3, mock2));
一样使用
这与when(something()).thenReturn(mock1, mock3, mock2);
答案 7 :(得分:0)
与8年前@ [Igor Nikolaev]的答案有关,可以使用Java 8中的lambda expression来简化Answer
的使用。
when(someMock.someMethod()).thenAnswer(invocation -> {
doStuff();
return;
});
或更简单地说:
when(someMock.someMethod()).thenAnswer(invocation -> doStuff());
答案 8 :(得分:0)
BDD样式:
import static org.mockito.BDDMockito.*;
...
@Test
void submit() {
given(yourMock.yourMethod()).willReturn(1, 2, 3);
答案 9 :(得分:0)
这里是BDD风格的工作示例,非常简单明了
given(carRepository.findByName(any(String.class))).willReturn(Optional.empty()).willReturn(Optional.of(MockData.createCarEntity()));
答案 10 :(得分:0)
您可以使用 LinkedList
和 Answer
。例如
MyService mock = mock(MyService.class);
LinkedList<String> results = new LinkedList<>(List.of("A", "B", "C"));
when(mock.doSomething(any())).thenAnswer(invocation -> results.removeFirst());