Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/373.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用Mockito对具有相同参数的同一方法进行多次调用_Java_Mocking_Mockito - Fatal编程技术网

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());