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
How to Mock Resultset and Populate It Using Mockito in Java
Java Input Validation for Number Range and Numeric Values Only With Counter
Keytool Error Bash: Keytool: Command Not Found
Type Safety: Unchecked Cast from Object to Arraylist<Myvariable>
How to Remove All Special Character in a String Except Dot and Comma
How to Read a File, Reverse the Order, and Write Reverse Order
How to Query Dynamodb Based on Partition Key and Sort Key [Java]
Java Generics Incompatible Types (No Instance(S) of Type Variable(S) Exist)
How to Input Date Using Sendkeys in Selenium Webdriver
Passing Data into HTML from Java Via Spring
How to Add Multiple Components to a Jframe
Object Cannot Be Converted to Integer Error
How to Set a Ttl for @Cacheable
How to Evaluate a Math Expression Given in String Form
How to Split Single Row into Multiple Rows in Spark Dataframe Using Java
How to Test If Json Collection Object Is Empty in Java
Every Digits in Number of a Range Should Be Is Divisible by N