How to return different results when calling the same mocked method?

Viewed 4336

I have a method that I call that connects to another server and each time I call it, and it returns different data.
I am writing a unit test for the class calling the method. I have mocked that class and I expect it to return the stubbed result. It actually works using doReturn, but it returns the same data every time. I want it to return different data and I want to be able to specify what it should be.

I tried using 'doReturn - when' and it works, but I can't make it return a different result. I don't know how to do this.

I also tried using 'when - thenReturn' which was the solution I found here on StackOverflow. With that, I could specify o get different responses every time I called the same method.

Problem is that I get a compilation error

The method XXX is undefined for the type OngoingStubbing<MyClass>

JSONArray jsonArray1 = { json array1 here };
JSONArray jsonArray2 = { json array2 here };

// Works but return the same jsonArray1 every time:
MyClass MyClassMock = mock(MyClass.class);
Mockito.doReturn(jsonArray1)
        .when(MyClassMock).getMyValues(any(List.class), any   (String.class), any(String.class),
                any(String.class),
                any(String.class));

// Does not work:
when(MyClassMock).getMyValues(any(List.class),
       any(String.class), any(String.class),
       any(String.class),
       any(String.class)).thenReturn(jsonArray1, jsonArray2);


// Compile error:
// The method getMyValues(any(List.class), any(String.class), any (String.class), any(String.class), any(String.class)) is undefined for the type OngoingStubbing<MyClass>

I get compile error:

The method getMyValues(any(List.class), any(String.class), any(String.class), any(String.class), any(String.class)) is undefined for the type OngoingStubbing

4 Answers

Make sure you put the mock + its method inside the when:

when(MyClassMock.getMyValues(any(List.class),
           any(String.class), any(String.class),
           any(String.class),
           any(String.class))
    .thenReturn(jsonArray1)
    .thenReturn(jsonArray2);

First you need to put the mocked method inside the when:

when(MyClassMock.getMyValues(any(List.class),
       any(String.class), any(String.class),
       any(String.class),
       any(String.class)).thenReturn(...);

Also if you want more controll about what is returned (e.g. depending on the input parameters of the method you should use an Answer instead of just returning values.

So this would be a better solution I think:

when(MyClassMock.getMyValues(any(List.class),
       any(String.class), any(String.class),
       any(String.class),
       any(String.class)).thenAnswer(new Answer<JSONArray> {/*Add implementation here*/});

Maybe this post can help using the Answer class of Mockito.

For normal mocks you can use something like this:

when(mockFoo.someMethod())
            .thenReturn(obj1, obj2)
            .thenThrow(new RuntimeException("Fail"));

If you are using spy() and the doReturn() instead of the when() method:

what you need to return different object on different calls is this:

doReturn(obj1).doReturn(obj2).when(this.client).someMethod();

This last suggestion worked!

Mockito.doReturn(obj1).doReturn(obj2).when(this.client).someMethod();

Thanks everyone for helping! / Jan

Related