Java 使用Mockito对具有相同参数的同一方法进行多次调用
有没有办法让存根方法在后续调用时返回不同的对象?我想这样做是为了测试来自Java 使用Mockito对具有相同参数的同一方法进行多次调用,java,mocking,mockito,Java,Mocking,Mockito,有没有办法让存根方法在后续调用时返回不同的对象?我想这样做是为了测试来自ExecutorCompletionService的不确定响应。i、 e.测试结果是否保持不变,与方法的返回顺序无关 我要测试的代码是这样的 // Create an completion service so we can group these tasks together ExecutorCompletionService<T> completionService = new Executo
ExecutorCompletionService
的不确定响应。i、 e.测试结果是否保持不变,与方法的返回顺序无关
我要测试的代码是这样的
// 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 (...) { }
}
//创建一个完成服务,以便我们可以将这些任务分组在一起
ExecutorCompletionService完成服务=
新执行人完成服务(服务);
//将所有这些任务添加到完成服务
for(可调用的t:ts)
完成服务。提交(请求);
//当每次调用完成时,将其添加到响应集中。
for(int i=0;i
您可以使用以下方法(链接时):
或使用等效的静态方法:
怎么样
when( method-call ).thenReturn( value1, value2, value3 );
只要参数类型正确,就可以在return的括号中放入任意数量的参数。第一次调用方法时将返回第一个值,然后返回第二个答案,依此类推。最后一个值将在所有其他值用完后重复返回。您甚至可以像这样链接
doReturn()
方法调用
doReturn(null).doReturn(anotherInstance).when(mock).method();
可爱吧:)因为几乎所有的电话都是可链接的
所以你可以打电话
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();
下面的详细信息可用作一个常用方法,在不同的方法调用上返回不同的参数。我们需要做的唯一一件事是传递一个数组,数组的顺序是在每次调用中检索对象的顺序
@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;
}
}
}
@SafeVarargs
子序列调用的公共静态应答getAnswerForSubsequentCalls(最终模拟…模拟){
返回新答案(){
私有整数计数=0,大小=mockArr.length;
公共模拟应答(InvocationMock调用)抛出可丢弃的{
Mock=null;
对于(;count我已经实现了一个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);
}
}
private final class MultipleAnswer实现应答{
私人最终ArrayList mAnswers;
多路应答器(应答…应答){
mAnswers=newarraylist();
addAll(Arrays.asList(answer));
}
@凌驾
公共T应答(调用锁调用)抛出可丢弃{
返回mAnswers.remove(0).应答(调用);
}
}
与8年前伊戈尔·尼古拉耶夫(Igor Nikolaev)的答案相关,使用答案
可以使用Java 8中可用的
when(someMock.someMethod()).thenAnswer(invocation -> {
doStuff();
return;
});
或者更简单地说:
when(someMock.someMethod()).thenAnswer(invocation -> doStuff());
BDD样式:
经典风格:
明确的风格:
doReturn(值1、值2、值3)。何时(方法调用)
下面是BDD风格的工作示例,非常简单明了
given(carRepository.findByName(any(String.class))).willReturn(Optional.empty()).willReturn(Optional.of(MockData.createCarEntity()));
您可以使用LinkedList
和.Eg
MyService mock=mock(MyService.class);
LinkedList结果=新的LinkedList(列表中的“A”、“B”、“C”);
when(mock.doSomething(any()).thenAnswer(调用->结果.removeFirst());
这将适用于模拟,但不适用于间谍。如果您需要阻止调用原始方法,则需要doAnswer(…).when(someSpy)。someMethod(…)。@Yuri-不完全正确。您不需要doAnswer
或在您提到的情况下编写答案
。您只需使用doReturn(…).when(someSpy)。someMethod(…)
。假设Emma对模拟而不是间谍感兴趣似乎是合理的,但我想我可以在我的答案中添加一些东西来说明这一点。谢谢你的评论。@DawoodibnKareem让我们说,第一次调用我想返回一个值,第二次调用我想抛出一个异常。这怎么办?@Rito请阅读第卷odymyr的答案或Raystorm的答案。它们都涵盖了这种情况。这是一个很好的答案。非常有用!第四次调用mock会发生什么情况。在这个示例中调用了方法
?我想要类似的东西,第一次返回foo,其余的都返回bar。对mock的每次额外调用都将返回最后一个“thenReturn”或last'Thenthorn'非常有用感谢您提供的伟大而简单的说明。直到现在我才知道这一点。我一直在努力寻找如何在两个相同的调用中返回两个不同的结果。为我节省大量时间。非常好的解决方案!使用它。您能以一种简短、简单且可读的方式初始化该对象吗?您是指doReturn吗(value1,value2,value3).when(mock).methodCall()
也许?这个答案对我帮助很大,因为doAnswer()
/thenAnswer()
不允许将多个调用链接为doReturn()
/thenReturn()
do,我需要计算一些东西,而不仅仅是返回一个不同的值。创建一个带有私有count
变量的匿名Answer
对象对我来说是个诀窍。请记住,当someMethod()
返回void
时,这些都是不等价的。有关详细信息,请参阅Answer。
when(someMock.someMethod()).thenAnswer(invocation -> doStuff());
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);
given(carRepository.findByName(any(String.class))).willReturn(Optional.empty()).willReturn(Optional.of(MockData.createCarEntity()));
MyService mock = mock(MyService.class);
LinkedList<String> results = new LinkedList<>(List.of("A", "B", "C"));
when(mock.doSomething(any())).thenAnswer(invocation -> results.removeFirst());