1

The question in the title isn't so clear, but I could't find a more suitable title. Currently I have to write tests (branch coverage) for a spring service (working with elasticsearch) and the method looks like this:

public CarSearchResult findCarData(final String name, final CarType carType){
     ....  search  .....
     return mapResponse(response);
}

private CarSearchResult mapResponse(final SearchResponse results) throws IOException {
   final CarSearchResult answer = new CarSearchResult();

   final List<Car> mappedCars = new LinkedList<>();

   for (SearchHit searchHit : results.getHits()) { <--  how to enter for-loop for testcoverage
       final CarObj carObj = map(searchHit);
       mappedCars.add(carObj );
   }
   answer.setCarObj(mappedCars);

   return answer;
}

mapResponse() gets the searchresults (doc) and these are further processed.

Inside my test class I have something like this:

@Mock private SearchResponse searchResponse;

// other Test cases for empty result worked because of this (case not entering the for loop)
when(searchResponse.getHits()).thenReturn(SearchHits.empty());

The problem is due to branch coverage I want to write a test which covers the case of having hits as well. But for this I would need Searchhits (doc). Does anybody know a way to enter this for-loop so branch coverage can be achieved?

I tried to find a way to return searchhits with when(searchResponse.getHits()).thenReturn( ..???.. ), but I don't know (or couldn't find) what should be returned so that I can cover the for-loop.

  • You'd just return a mock of `SearchHits`… did you try that? – slauth Oct 22 '21 at 06:37
  • Do you mean when(searchResponse.getHits()).thenReturn(searchHits) (@Mock private SearchHits searchHits;)? I already tried this, but it leads to nullpointer exception – JohnBenjamin Oct 22 '21 at 06:57
  • This is because you have to define the desired behavior of the mock… i.e. you have to mock the `iterator()` method. – slauth Oct 22 '21 at 07:05

1 Answers1

2

You have to return a mock of SearchHits, with the iterator() method being mocked (because that's what called behind the scenes in the for loop):

@Mock SearchHits searchHits;
@Mock SearchHit searchHit;

when(searchHits.iterator()).thenReturn(singleton(searchHit).iterator());
when(searchHit.docId()).thenReturn(42);

Note that because both SearchHits and SearchHit are final classes you have to ensure that Mockito is able to mock final classes.

slauth
  • 2,667
  • 1
  • 10
  • 18