Wednesday, December 25, 2013

Return a mock value when an object is being spy

My objective is to develop a test stub that will return me a true value whenever the following method is invoked.
public class ReportService {

    protected boolean readInRawReport(Vector inputFileNameList) {
        boolean found = true;

        for( String inputFileName : inputFileNameList ) {
        ...
        ...
    }
    ...
    return found;
}
I was unit testing the code snippet above using the stub code shown below, unfortunately the test was failed due to NullPointerException happened on inputFileNameList.
public class HibernateReportServiceStubber<T extends HibernateReportService<Object>> {

 private T daoReportService;

 public void readInRawReportReturnTrue() throws Exception {
  PowerMockito.when(this.daoReportService, PowerMockito.method(ReportService.class, "readInRawReport"))
  .withArguments(Mockito.any(Vector.class))
  .thenReturn(true);
 }

 ...
}

This is not supposed to happen when an object is being mock. During the investigation, I found it interesting when I’m tracing the code in debug mode, the code were actually flow into the real method, and inputFileNameList is showing NULL. My first question to myself is why do I need to bother the details implementation since I’m doing mocking? Is that mean Mockito.any() not doing his job? But later I found out I'm actually spying the test object, not mocking. Opps... To prove my justification is correct, I make some changes on the code like this:
  Vector<String> v = new Vector<String>();
  v.add("ASD");

  PowerMockito.when(this.daoReportService, PowerMockito.method(ReportService.class, "readInRawReport"))
  .withArguments(v)
  .thenReturn(true);

Now I can see inputFileNameList is having one element which shows ASD in it. The return value has nothing to do with thenReturn() and this function were totally disabled because the control has already been transfer into the hand of the real method when the test object is being spy. I wonder whether is this the right way to do this? Fortunately, I was so lucky that I manage to find the right way to do this. Thank God. Here is the correct solution on mocking the return value when a test object is being spy is shown below:
  PowerMockito.doReturn(true)
  .when(this.daoReportService, PowerMockito.method(ReportService.class, "readInRawReport"))
  .withArguments(Mockito.any(Vector.class));
This was like an English grammar, tweak from active sentence to a passive sentence.

No comments: