是否有一种方法可以让存根方法在后续调用时返回不同的对象?我希望这样做是为了测试来自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);

其他回答

我已经实现了一个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);
    }
}

这可能是基本的/明显的,但如果像我一样,你试图模拟一个方法的多次调用,每次调用要测试的方法被调用未知次数,例如:

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

这和问题没有直接关系。但我想把这个放在同一个链上。

如果试图用多个参数验证同一个方法调用,可以使用Mockito的下面的times特性。如果你不验证,你就不需要它。

5。验证((n)方法,倍).methoscall ();

这里的“n”是调用mock的次数。

正如前面指出的,几乎所有的调用都是可链的。

所以你可以打电话

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的文档。

这里是BDD风格的工作示例,非常简单和清晰

given(carRepository.findByName(any(String.class))).willReturn(Optional.empty()).willReturn(Optional.of(MockData.createCarEntity()));