Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mock same method with different parameters

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   } } 
like image 504
Zeeshan Bilal Avatar asked Jan 20 '17 15:01

Zeeshan Bilal


People also ask

How do you mock the same class method?

We can mock runInGround(String location) method inside the PersonTest class as shown below. Instead of using mock(class) here we need to use Mockito. spy() to mock the same class we are testing. Then we can mock the method we want as follows.

How do you inject multiple mocks of the same interface?

Your test class should be: @RunWith(SpringRunner. class) class ServiceLayerTest{ @Mock(name = "typeA") private InterfaceA typeA; @Mock(name = "typeB") private InterfaceA typeB; @InjectMocks ServiceLayer serviceLayer; @Before public void initialiseBeforeTest(){ MockitoAnnotations.

Is Mockito mock same as @mock?

They both achieve the same result. Using an annotation ( @Mock ) is usually considered "cleaner", as you don't fill up your code with boilerplate assignments that all look the same.

What is the difference between doReturn and thenReturn?

One thing that when/thenReturn gives you, that doReturn/when doesn't, is type-checking of the value that you're returning, at compile time. However, I believe this is of almost no value - if you've got the type wrong, you'll find out as soon as you run your test. I strongly recommend only using doReturn/when .


1 Answers

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")); 
like image 58
Nicolas Filotto Avatar answered Sep 30 '22 06:09

Nicolas Filotto