How to Return Different Results When Calling the Same Mocked Method

Mocking two different results from the same method

You can use a function in the Returns of the Setup to execute custom logic based on provided input when the mocked member is called.

_moqDB
.Setup(_ => _.EditStaff(It.IsAny<StaffEditViewModel>()))
.Returns((StaffEditViewModel arg) => {
if(arg != null && arg.StaffID == 887) return true;
else return false; //this will satisfy other Ids like 1
});

_moqDB
.Setup(_ => _.DeleteStaffMember(It.IsAny<int>()))
.Returns((int staffId) => {
if(staffId == 887) return true;
else return false; //this will satisfy other Ids like 1
});

You can implement what ever logic within the Func to satisfy multiple scenarios for your tests.

Also as mentioned in the comments try to arrange once per test so that setups do not override each other when run together as the last setup on a member will override any previous ones that match. It simplifies that testing process as each unit test should be run in isolation and should not be affected by other tests in the list.

Mockolate - Calling the same method on a mock with the same arguments but return different results

This bugged the hell out of me, until I found out it is really very simple: Just use all the expected return values as parameters to the first returns() statement.

 expect(list.getItemAt(0)).returns("Item1", "Item2", "Item3", "Item4").inSequence(seq); 

The mock will return the last of these parameters for each subsequent call.

Using Mockito with multiple calls to the same method with the same arguments

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

Mockito mock same method calls with different collection-arguments

Your second call - Mockito.when(c.run(b)).thenReturn("b");
is overruling our first call so Mockito will therefore always return "b".
If you need multiple answers from the same call, you can use the varags variant:

when(c.run(anyCollection())).thenReturn("a", "b");

Now the first call to the controller's run method will return "a" and all subsequent calls will return "b". You can provide as many return results as you want and the last one will be repeated from then on as the answer.

In Mockito, what's the proper way to return different results upon conseuctive calls to a non-static method?

Mockito.when(connection.query(Mockito.anyString())).thenReturn(queryResults1).thenReturn(queryResults2);

Since you dont want the query to be executed you should use this format
doReturn(...).when(..).

Mockito.doReturn(queryResults1).doReturn(queryResults2).when(connection).query(Mockito.anyString())

There is no difference between the above statements if you mock the oject. But if you are using spy, When(...).thenReturn() will call the real method first before returning. So you should use doReturn(...).when(..) in this case.

More about it here

Mock same method with different parameters

One way could be to avoid being too restrictive on your arguments in order to provide all the expected results with only one thenReturn call.

For example let's say that I want to mock this method:

public String foo(String firstArgument, Object obj) {
return "Something";
}

You could then mock it by providing as many results as you want like below:

// Mock the call of foo of any String to provide 3 results
when(mock.foo(anyString(), anyObject())).thenReturn("val1", "val2", "val3");

Calls to foo with any parameters will provide respectively "val1", "val2", then any subsequent calls will provide "val3".


In case you do care about passed values but don't want to depend on call sequence you can use thenAnswer to provide an answer that matches with the second argument like you currently do but with 3 different thenReturn.
Assuming that you have overridden the method equals(Object o).

when(mock.foo(anyString(), anyObject())).thenAnswer(
invocation -> {
Object argument = invocation.getArguments()[1];
if (argument.equals(new ARequest(1, "A"))) {
return new AResponse(1, "passed");
} else if (argument.equals(new ARequest(2, "2A"))) {
return new AResponse(2, "passed");
} else if (argument.equals(new BRequest(1, "B"))) {
return new BResponse(112, "passed");
}
throw new InvalidUseOfMatchersException(
String.format("Argument %s does not match", argument)
);
}
);

Or simply, using the methods anyString and eq as argument marchers.
Assuming that you have overridden the method equals(Object o).

when(service.foo(anyString(), eq(new ARequest(1, "A"))))
.thenReturn(new AResponse(1, "passed"));
when(service.foo(anyString(), eq(new ARequest(2, "2A"))))
.thenReturn(new AResponse(2, "passed"));
when(service.foo(anyString(), eq(new BRequest(1, "B"))))
.thenReturn(new BResponse(112, "passed"));

How do I return different values on different calls to a mock?

Mockito supports changing the returned value; this support extends to PowerMockito. Just use OngoingStubbing.thenReturn(T value, T... values)

OngoingStubbing<T> thenReturn(T value, T... values)

Sets consecutive return values to be returned when the method is called.

E.g:

when(mock.someMethod()).thenReturn(1, 2, 3);

Last return value in the sequence (in example: 3) determines the behavior of further consecutive calls.

So, in this case, you would do:

PowerMockito.when(DBUtil.getCurrentCount()).thenReturn(100, 150);

Note: this answer assumes you already know how to mock static methods. If you do not, see this question.



Related Topics



Leave a reply



Submit