2

I'm trying to figure my way around mocking this guy. I have Mockito blessed through Surefire:

@Inject
private javax.ws.rs.client.Client client;
...
String response = client.target(url).request(MediaType.APPLICATION_JSON).post(Entity.entity(request, MediaType.APPLICATION_JSON), String.class);

Results in some really awful mocking:

doReturn(mockWebTarget).when(mockClient).target(url);
doReturn(mockBuilder).when(mockWebTarget).request(MediaType.APPLICATION_JSON);
doReturn(response).when(mockBuilder).post(any(Entity.class), eq(String.class)); // <- really need to inspect that entity

client is injected (Spring). no problems at runtime, but pain in test.

  • boilerplate rest client chain
  • have to verify a nested object to post()
  • prefer to avoid chaining mocks
  • chain has multiple classes (i.e., not a typical builder)
  • chained mock failures just give a null pointer exception to diagnose
  • fragile to maintain and unhelpful when it fails

My main problem is if there is any problem, it just throws nulls when a mock return fails and i dereference in the chain.

Is there a good pattern for this?

  • edit -

Fished my wish

Discovered Captors and I think I get the philosophy now.

The approach is to get through the chain with a lot of any() matchers. This basically collapses the chain call so I can worry about entry and exit points.

Then I can retroactively capture the end of the chain with verify() and captors to inspect the post() in the middle after the fact, and just beat the heck out of it.

There was also an opportunity to look at arguments added in the chain and try and reduce them - in my case I could replace post(entity,String.class) with postJson(entity). Didn’t even know the alternative existed.

  • "*I have Mockito blessed through Surefire*" - What? --- "*Is there a good pattern for this?*" - Yes: use less mocking. This will, however, come with its own challenges since we start writing integration tests. --- A remark: I would suggest using `when(...).thenReturn(...)` instead of `doReturn(...).when(...)` since the former guaranteees type safety at compile-time. – Turing85 Sep 17 '20 at 12:42
  • Agree with all your points, but testing requests is often complex. Not sure if using the javax client is important but with spring you can use RestTemplate or WebClient. They don't require chaining. However, they can still get messy with complicated requests and assertions. Integration tests or contract tests might also meet your needs but they can also get complicated in other ways. – DCTID Sep 18 '20 at 02:18
  • My department allows Mockito but not others like powermock. I’m driving tests in maven through the surefire plugin. – Matty Thompson Sep 18 '20 at 18:20

0 Answers0