Mock same method with different parameters
Solution 1
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"));
Solution 2
The proper way would be to match the arguments using eq()
, but if you don't want to do that, you can just record multiple return values.
when(someService.doSomething(any(SomeParam.class))).thenReturn(
firstReturnValue, secondReturnValue, thirdReturnValue
);
Now the first call will return firstValue
, the second secondValue
and all following thirdValue
.
Solution 3
If you are mocking the method just want to verify that the correct arguments are being passed in, you can use any() and verify with ArgumentCaptor following the mocked method call.
Zeeshan Bilal
I am a seasoned engineer & architect equipped with analyses, design, architecture, development & management skills. During my 17 years of experience I have ● Directed many teams, products and projects from requirement to deployment and then support/maintenance on production using different Agile methodologies. ● Managed requirements, risks, technical teams (resource hiring, mentoring & training), project level activities, track plans & report to management. ● Built new and improved existing products’ design/architecture to achieve different functional and non functional goals like security, resilience, fault tolerance, scalability, performance and technology. ● Develop software/products from different business domains specially IIoT/Industrial Automation/ EMR, Medical billing etc. Technical Specialties: Java/JEE based technologies(JSF, EJB, Spring, Hibernate, Web services), Cloud (GAE, Amazon, Cloudfoundry), Mobile (iPhone, Android) and cutting-edge enterprise business solutions. Also have experience working on some modern technologies like Amazon (EC2, S3, Lambda), Cloudfoundry, OSGi, JBoss Rules, Lucene, Scala and Akka.
Updated on July 09, 2022Comments
-
Zeeshan Bilal 6 months
I am using mockito to test my business service, and it uses a utility that i want to mock. there are at least 2-3 calls in each service method for utility with different arguments.
Is there any recommended way to use multiple
when(...).thenReturn(...)
for same method but different arguments?I also want to use
any()
marcher as well inside. Is it possible?Update: sample code.
@Test public void myTest() { when(service.foo(any(), new ARequest(1, "A"))).thenReturn(new AResponse(1, "passed")); when(service.foo(any(), new ARequest(2, "2A"))).thenReturn(new AResponse(2, "passed")); when(service.foo(any(), new BRequest(1, "B"))).thenReturn(new BResponse(112, "passed")); c.execute(); } public class ClassUnderTest { Service service = new Service(); public void execute() { AResponse ar = (AResponse) service.foo("A1", new ARequest(1, "A")); AResponse ar2 = (AResponse) service.foo("A2", new ARequest(2, "2A")); BResponse br = (BResponse) service.foo("B1", new BRequest(1, "B")); } } public class Service { public Object foo(String firstArgument, Object obj) { return null; //return something } }