Yesterday, I wrote about custom Mockito matchers and this article is an example of a real usage of these matchers. In my code, I often use wrapper services that call distant APIs. The service builds a JSONObject that will be sent to the server so I need to make sure that it is correct. In order to do that, I need a custom JSON Mockito matcher.

The class UserService will use the class ApiWrapper in order to create a user on a distant account server. Here is the first test I wrote:

@Test
public void test_user_is_posted_to_distant_server() {
	// GIVEN
	ApiWrapper apiWrapper = mock(ApiWrapper.class);
	UserService userService = new UserService(apiWrapper);

	User user = new User();
	user.setEmail("vdurmont@gmail.com");
	user.setName("Vincent DURMONT");

	// WHEN
	userService.create(user);

	// THEN
	JSONObject json = new JSONObject();
	json.put("email", user.getEmail());
	json.put("name", user.getName());

	verify(apiWrapper).post(json);
}

But when I run the test, I got this failure:

Argument(s) are different! Wanted:
apiWrapper.post(
	{"email":"vdurmont@gmail.com","name":"Vincent DURMONT"}
);
-> at com.github.vdurmont.AppTest.test_user_is_posted_to_distant_server(AppTest.java:34)
Actual invocation has different arguments:
apiWrapper.post(
	{"email":"vdurmont@gmail.com","name":"Vincent DURMONT"}
);
-> at com.github.vdurmont.service.UserService.create(UserService.java:18)

/*
I got this failure:

java.lang.AssertionError
	at org.junit.Assert.fail(Assert.java:86)
	at org.junit.Assert.assertTrue(Assert.java:41)
	at org.junit.Assert.assertTrue(Assert.java:52)
	at com.github.vdurmont.AppTest.test_json_equals(AppTest.java:25)
 */

This is due to the fact that JSONObject doesn’t override the method equals so when Mockito uses the default equals matcher, it fails.

In order to have a simple verification, I wrote 2 custom matchers: one for JSONObject and one for JSONArray.

You can find the code on github.