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

当前回答

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

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

其他回答

与8年前@[Igor Nikolaev]的答案相关,使用Java 8中的lambda表达式可以在一定程度上简化answer的使用。

when(someMock.someMethod()).thenAnswer(invocation -> {
    doStuff();
    return;
});

或者更简单地说:

when(someMock.someMethod()).thenAnswer(invocation -> doStuff());

你可以使用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();

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

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

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

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

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

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

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