Integration Testing with Spring: Consumers

Gil Zilberfeld explains how to mock API calls for integration tests
Standard
In this series we're taking at Spring and its features supporting testing in general, and specifically integration tests.
Dependency injectionConfigurationsNested configurationsOrganizing configurations
Primary beansAvoiding problemsProfilesMocking I - Lifecycle
Mocking II - ResetMocking III - MockBeanData I - @SQLData II - JDBC

Data III - JPA
Controllers IControllers IIConsumer tests

We’ve been through a lot. We’ve covered all kinds of flows to be tested on the server side. We’ve seen how to check flows from the controller down to the database, combined with injecting different mocks and services. We’ve got one more thing: What happens if my controller (or any other component) makes an external API call. I may want to mock that call. Does String help?

Here’s our client. It calls the ItemController from last time, through its API:

We need to supply the RestTemplate through configuration . Just create one, it’s created in the context of the WebApplication, and therefore the web container that Spring runs. The RestTemplate is very helpful in posting and getting, and making HTTP API calls. If something bad happens, it throws an exception we can check and do something about it.

So if we want to check the logic of our client in an integration test, we would want to mock the API call. We can, as we’ve seen before, inject a mock RestTemplate, and tell it what to return. That’s kids stuff. But then everybody will make their own mock, and that’s a waste.

So, of course, we get a Spring solution. It’s got the sexy name MockRestServiceServer. Yeah, I know, but it does what it says on the label.

In order to create one, we need to remember that the RestTemplate we use is connected to the test server. when we run the integration test. We need to have a shared RestTemplate between our client-under-test, and the integration test itself, and Spring happily injects one for us. It’s still a regular RestTemplate:

Once we’ve got a configuration, we can use it in our integration test class:

Then we build our MockRestServiceServer manually, using our RestTemplate. Or if we’re lazy, Spring gives as an annotation to inject the MockRestServiceServer automatically, so we don’t have to build it ourselves (or the RestTemplate):

Now that we got mock what are we gonna do with it? For the first integration test, let’s configure it to return a value that doesn’t trigger an exception.

Just like good ol’ EasyMock, but at the API level, we can set expectations, behavior and verify those callse.

For the second integration test, we’ll ask the mock to return a bad request answer that will result in throwing the exception:

That’s pretty nifty. We can control dependent services in our integration tests.

We can have the client call the the server, if it makes sense. For example, if we can set up the database and configure it, we can check the integration between the services.

Remember, the longer the sequence, the bigger the setup, and the chance of the flow breaking on something else rises too. There are cases though when mocking is necessary, if we don’t control the server, of if the server returns a different result every time. Think an API that returns the global time or weather. These are hardly repeatable. And controlling the weather is even harder.

Leave a Reply

Your email address will not be published. Required fields are marked *