Home Blog CV Projects Patterns Notes Book Colophon Search

HTTP Test Double

24 Jun, 2015

In microservices architecture, you often want to test a particular service from the outside. But what happens if that service relies on another services that uses an HTTP API. As an example, consider a billing service that communicates with GoCardless or Stripe via HTTP to actually take payments.

There are a few approaches here:

  1. Use a sandbox account on the other service and let the system under test make reall HTTP requests to the sandbox to test that too
  2. Set up a fake service that behaves the same as the real service
  3. Point the service under test at an HTTP test double driven from the test runner to send fake responses back to the service

The sandbox option is very robust and it will pick up any changes in the payment services API, but it might be slow or awkward to run specific tests against it, or set up fixtures (particularly those that reply on a browser based registration of a user rather than the payment API itself).

The fake service is a bit of a non-starter - you'd end up building an almost real solution just to run tests - frequently this will be just too costly.

The third option is the one solved by my http-test-double code. I wrote it one day with Vlad Mettler using a TDD approach for the test double code itself.

The basic idea is that before you send any command to the system under test, you first send a command to the test double server telling it what it should expect to receive from the service under test and the response it should send back:

Tests          Service under test      Test Double Server
  |                    |                       |

  | Setup Response                             |
  +------------------------------------------->+
  | Test Request                                
  +------------------->+                        
                       | External Request       
                       +---------------------->+
                         Programmed Response   |
                       +<----------------------+
    Response           |                        
  +<-------------------+                        

This approach allows you to test the entire service in isolation. It doesn't stop the external service from changing so you still need separate integration tests between the service under test and the external service.

You can see the code here:

Note: This version is based around TypeScript. I wouldn't use TypeScript for this now, so the codebase needs updating.

Copyright James Gardner 1996-2020 All Rights Reserved. Admin.