Vikas Gupta: Software architect

Capturing methods arguments with Mockito

Posted by Vikas Gupta on September 22, 2012

In my project, we developed an API for searching on the lines of Hibernate Restrictions API. It was for Solr search. A sample code looked something like

 public SearchResults searchApprovedRecipes(String searchText, Integer pageNum) {
 SolrSearchServiceImpl.PageCounter pageCounter = new SolrSearchServiceImpl.PageCounter(pageNum);

 SearchCriteria searchCriteria = new SearchCriteria(SearchCriteria.SearchType.RECIPE);
 searchCriteria.add(SearchCriteria.SearchField.NAME, searchText);
 searchCriteria.add(SearchCriteria.SearchField.STATUS, WorkflowStatus.APPROVED.name(), WorkflowStatus.EDITED.name());
 searchCriteria.setMaxResults(pageCounter.getMaxResults());
 searchCriteria.setStart(pageCounter.getStart());

 SearchResults searchResults = getRestTemplate().postForObject(getSearchUrl(), searchCriteria, SearchResults.class);

 return searchResults;

Now, if you talk about unit testing, there is nothing much to test, except mocking calls to rest template. The main purpose of this method is to build SearchCriteria. So, if somehow, we can mock SearchCriteria, then we could test that.

Mockito comes with a concept of capturing the arguments passed to the mocked calls (in this case, call to RestTemplate would be mocked), using ArgumentCaptor, which captures argument values for further assertion.

Following is the unit test case of the above method.

@Test
 public void testSearchApprovedRecipes() {
 ArgumentCaptor<SearchCriteria> searchCriteriaArgumentCaptor = ArgumentCaptor.forClass(SearchCriteria.class);
 String test = "test";
 solrSearchService.searchApprovedRecipes(test, 1);
 verify(restTemplate, times(1)).postForObject(eq(SEARCH_URL), searchCriteriaArgumentCaptor.capture(), eq(SearchResults.class));

SearchCriteria searchCriteria = searchCriteriaArgumentCaptor.getValue();
 Assert.assertEquals(2, searchCriteria.getSearchFields().size());
 Assert.assertEquals(SearchCriteria.SearchType.RECIPE, searchCriteria.getSearchType());
 Assert.assertEquals(test, searchCriteria.get(SearchCriteria.SearchField.NAME).get(0));
 Assert.assertTrue(searchCriteria.get(SearchCriteria.SearchField.STATUS).contains( WorkflowStatus.APPROVED.name()));
 Assert.assertTrue(searchCriteria.get(SearchCriteria.SearchField.STATUS).contains( WorkflowStatus.EDITED.name()));
 }

In the above code, you can see that first we created a ArgumentCaptor for the SearchCriteria class, and then, while mocking call to the RestTemplate, instead of passing the SearchCriteria object, we passed the ArgumentCaptor and all the changes made to the SearchCriteria inside the method are captured in the ArgumentCaptor. Now, once the method calls return, we can have assert statements against the ArgumentCaptor. This way, we can test the SearchCriteria.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: