添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

Is there a way to have a stubbed method return different objects on subsequent invocations? I'd like to do this to test nondeterminate responses from an ExecutorCompletionService . i.e. to test that irrespective of the return order of the methods, the outcome remains constant.

The code I'm looking to test looks something like this.

// 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 (...) { }        
                This will work with a mock, but not with a spy. If you need to prevent calling the original method you need doAnswer(...).when(someSpy).someMethod(...).
– Yuri
                Dec 11, 2014 at 0:01
                @Yuri - not quite.  You don't need doAnswer or to write an Answer in the case that you mention.  You can just use doReturn(...).when(someSpy).someMethod(...).  It seems reasonable to assume that Emma is interested in mocks, rather than spies, but I guess I could add something to my answer to spell this out.  Thanks for the comment.
– Dawood ibn Kareem
                Dec 11, 2014 at 0:06
                @DawoodibnKareem lets say for the first call I want to return a value and for the second call I want to throw an Exception. How can this be done?
– Rito
                Sep 11, 2017 at 12:18
                Wow, have wasted almost 3 hours debugging HashSet, Spring beans...others, in a loop of 3, thenReturn was giving the same mock object, which results in same hashCode in HashSet, which results in HashSet having 1 element instead of 3 elements, which results in test case failures due to assertion. Thanks.
– Yoga Gowda
                Oct 5, 2019 at 19:22

You can do that using the thenAnswer method (when chaining with when):

when(someMock.someMethod()).thenAnswer(new Answer() {
    private int count = 0;
    public Object answer(InvocationOnMock invocation) {
        if (count++ == 1)
            return 1;
        return 2;

Or using the equivalent, static doAnswer method:

doAnswer(new Answer() {
    private int count = 0;
    public Object answer(InvocationOnMock invocation) {
        if (count++ == 1)
            return 1;
        return 2;
}).when(someMock).someMethod();
                This answer helped me a lot because doAnswer()/thenAnswer() do not allow chaining multiple calls as doReturn()/thenReturn() do and I needed to compute something and not just return a different value. Creating an anonymous Answer object with a private count variable was what did the trick for me.
– Lucio Paiva
                Aug 20, 2020 at 18:19
                Keep in mind that these are not equivalent when someMethod() returns void. See this answer for more details.
– Raphael
                Nov 18, 2020 at 23:17
                @LucioPaiva Where do you get the information, that you can not chain "doAnswer" calls with other calls? Is this a known bug, feature or something else?
– KFleischer
                Jun 12 at 8:59
                @KFleischer You CAN chain doAnswer calls, and also mix them with other do... calls.  You can also chain thenAnswer calls, and mix them with other then... calls.  I believe Lucio has made a mistake.
– Dawood ibn Kareem
                Sep 28 at 8:23

So you could call

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

More info in Mockito's Documenation.

Very helpful! What would happen the 4th time mock.method was called in this example? I want something like, return foo the first time but return bar for ALL the rest. – javaPlease42 Jan 20, 2016 at 21:52 Each additional invocation on the mock will return the last 'thenReturn' or the last 'thenThrow' Very useful – Francois Lacoursiere Jan 22, 2016 at 21:48 Thank you for the great and simple instructions. Never knew this until now. I was struggling to find how to get back two different results on two identical call. Save me tons of time. – CharlesC Sep 26, 2019 at 14:45

Depending on an arg

Option #1

Suppose we have 2 args, and check the size of the 2nd (list) arg:

when(yourMock.yourMethod(any(), anyList())) .thenAnswer(args -> ((List) args.getArgument(1)).size() < 2 : 3);

args are Objects, so we have to cast an arg to our type. I cast ^^^ to (List) in my case.

Option #2 (BDD)

given(yourMock.yourMethod(any(), anyList())) .willAnswer(args -> ((List) args.getArgument(1)).size() < 2 : 3);

I've implemented a MultipleAnswer class that helps me to stub different answers in every call. Here the piece of code:

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

Related to @[Igor Nikolaev]'s answer from 8 years ago, using an Answer can be simplified somewhat using a lambda expression available in Java 8.

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

or more simply:

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

This is not directly related to the question. But wanted to put this in the same chain.

If trying to verify the same method call with multiple arguments, you can use the below times feature by Mockito. You don't need it if you are not verifying.

Mockito.verify(method, times(n)).methoscall();

Here is 'n' is the number of times the mock is invoked.

If you have a dynamic list of values you can use AdditionalAnswers.returnsElementsOf:

import org.mockito.AdditionalAnswers;
when(mock.method()).thenAnswer(AdditionalAnswers.returnsElementsOf(myListOfValues));

Following can be used as a common method to return different arguments on different method calls. Only thing we need to do is we need to pass an array with order in which objects should be retrieved in each call.

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

Ex. getAnswerForSubsequentCalls(mock1, mock3, mock2); will return mock1 object on first call, mock3 object on second call and mock2 object on third call. Should be used like when(something()).doAnswer(getAnswerForSubsequentCalls(mock1, mock3, mock2)); This is almost similar to when(something()).thenReturn(mock1, mock3, mock2);

You can use a LinkedList and an Answer. Eg

MyService mock = mock(MyService.class);
LinkedList<String> results = new LinkedList<>(List.of("A", "B", "C"));
when(mock.doSomething(any())).thenAnswer(invocation -> results.removeFirst());

This might be basic/obvious, but if like me you are trying to mock multiple calls for a method that is called unknown number of times per call to method to be tested, for example:

public String method(String testArg) {
    //...
    while(condition) {
        someValue = someBean.nestedMethod(); // This is called unknown number of times
        //...
    //...

You can do something like:

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

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.