I recently pushed a project called Pre-canned up onto github. Pre-canned is a Scala tool that helps you to mock out HTTP services. Why would you want to do that?
In an ideal world, we would always run integration tests for our application in a real environment, using the real HTTP services our application relies on. However, this can prove difficult for several reasons:
- It is difficult to insert test data into the HTTP services you depend on – Some services you rely on may be read-only with no way to insert test data. This can be especially true for APIs provided by a third-party for which you don’t even have ability to add a write API for testing purposes. Mocked services can simply serve test data from a static file that you control. Easy!
- The HTTP services you depend on are slow – Your integration test suite becomes less useful if it takes a long time to complete. A slow test suite will also hinder continuous delivery and the ability to deploy at any time. Since mocked services aren’t actually doing any work, they can be as quick as you need.
- The HTTP services you depend on are invisible from the outside – Say that behind the scenes your application calls out to an analytics or metrics recording service. This call may not visible in the public API your application exposes, so how do you write an integration test that checks you are still making these calls? A mocked service can incorporate call verification. Several Java HTTP mocking libraries I have used in the past support this, including restito, wiremock and rest-driver. Pre-canned does not currently support this, but it is one of the things I would like to add in the near future.
- The HTTP services you depend on are non-deterministic – Say your application calls an API that returns the current status of the weather. The response from this API will change constantly, which can make it hard to make valid assertions that your application is doing the right thing. Mocked services are stable and allow you to define exactly the data you want to use for a given test case.
There are, however, some downsides to mocking HTTP services:
- Overhead of maintaining the mocked data – If the APIs you rely on change, then you will need to update all the test data your mocked services serve up. You could argue that this overhead is comparable to the work required for preparing test data if you are using the real APIs
- Mocks are not real – There are always going to be differences between the way your mocked services and the real services behave
Load testing is another use case for mocking the service you depend on. Load testing your application in the real environment will give you a good idea of the performance your users will be seeing. But how much of that latency is caused by your application, and how much is caused by the services your application depends on? One way to check this is to mock out all the services you depend on, re-run your load tests and compare the results.