Showing posts with label junit. Show all posts
Showing posts with label junit. Show all posts

Saturday, February 10, 2018

Mockito : Argument Captor - catches reference and not value

This is the service to test :

public void method(List<String> inputs) {

   Map<String,Object> parameterMap = new HashMap<>();

   parameterMap.put("common_attr1","blah");
   parameterMap.put("common_attr2","blah");

   for(String input: inputs) {
       parameterMap.put("selector",input);
       dao.makeDBCall(parameterMap);
   }

}

To collect the argument passed to the DB call, you would ideally go for the ArgumentCaptor and see if each call is made with the corresponding input passed to the method()


But, this will not work because ArgumentCaptor gives you the reference. so all the captured value will point to the argument corresponding to the last call made to the DB call.

Solution :

Use thenAnswer to collect the parameters while invoking the DB call.

List<String> actualSelectorsPassedForInputs = new ArrayList<>();
when(dao.makeDBCall(anyObject())).thenAnswer(invocation->{
 Object[] args = invocation.getArguments();
 HashMap<String,Object> parameterMap = (HashMap<String,Object>) args[0];
 actualSelectorsPassedForInputs.add(parameterMap.get("selector"));
});

// do assertions on actualSelectorsPassedForInputs

Reference :
1) https://stackoverflow.com/questions/11984128/capturing-previous-values-to-verify-mock-object

Wednesday, May 31, 2017

Junit : Mocking a method of spy

I came across a test case failure in my project. The method mocked using spy was something like
public class Service {
 public String foo()
 {
  return "dummy";
 }
}

And in the test cases
private Service spyService;

@Test
public void test()
{
 String test = "test";
 when(spyService.foo()).thenReturn(test);
}

We did some changes in the Service to cache the reference values during initialization and use the map to get the values.

public class Service {
 private Map cache;
 ...
 public String foo()
 {
  return cache.get("someKey");
 }
}
And now the test cases started throwing NPE at cache.get() in Service's foo

Why is this? When you use spy, the method actually gets called. That's why before adding the cache, it was working fine.

So when you are using when on spy, call doReturn first. This will prevent the method being mocked from getting executed.

doReturn(test).when(spyService).foo();

Read this for more details.
Be careful when using spy in junit tests.