How To Not Stub Your Toe In Production

How To Not Stub Your Toe In Production

Application testing from the Network and Platform Engineering lens

I’ve hit a stub, what did I do…right?!

Coming from a networking engineering background, it’s always challenging to understand the behaviours of applications and how they’re expected to respond. Networks have a high-degree of automation to accommodate for changing conditions, or failures along the path, but this isn’t always tuned towards the application itself. Before you even launch your application into production, you still want to understand how it might perform in a scenario of high network latency or path failures. You also might be interested to know how an application would normally respond prior to being pushed to production.

Let’s take a scenario where you currently run Kubernetes, and you might be using a service mesh to provide service-to-service logic and connectivity, but how can you go about simulating a failure in your application? A service mesh can be tuned to accommodate for failures, in fact, you can use the sidecar proxy to return responses on behalf of a service.

Let’s visualize the flow of a request within a Kubernetes environment:

Let’s get stubby with WireMock

A more developer-driven approach exists that allows for canned responses to simulate an API that an application developer has created. Using a stub-like system you can simulate full application responses and tie them to various backend URIs. While a service mesh like Istio can be tuned to simulate faults and failures, it can’t quite fully respond back to a client with an appropriate canned response. Something else has to… How about a WireMock stub?

Using a WireMock HTTP mock server you can deploy a “stub”, which can simulate an API and its expected responses and gather the necessary feedback and metrics to determine if your pre-production API is ready…for production.

How does this help Platform Engineers with assessing and observing application behaviour?

Using the HTTP Mock server, canned responses can be returned to simulate a service, as simple as the “hello world” service. For example, when you make an API call to the Hello World service, you would expect it to succeed (with a HTTP status code of 200), but also return some response. With a stub, the expected response can be more than just a “Hello” reply from your service.

This can be extremely useful, especially with Blue/Green, canary or Dark Launches, especially for pre-production assessment.

So what exactly is WireMock’s functionality as an HTTP server? Let’s dig into some basics.

  1. Request matching: WireMock can match incoming HTTP requests based on various criteria like headers, HTTP request method, URL, or request body. Define a stub with a specific request pattern, and WireMock responds with a predefined/canned response upon a pattern match.

  2. Response templating: WireMock enables you to create dynamic responses using placeholders, logic, and data from the incoming request. This feature is useful for simulating real-world API responses.

  3. Baselining and playback: WireMock can record API interactions and save them as stub mappings, which can later be played back during testing. This is extremely powerful as a feature if you need to develop test cases quickly based on how your APIs behave.

  4. Stateful services: WireMock supports stateful services which allow for simulating complex state transitions in APIs, for example, using authentication.

  5. Service Proxying: The WireMock server can proxy requests on behalf of another service and record the request flow.

  6. Injecting Faults: WireMock allows you to simulate various types of network faults and server errors, helping you test your application's resilience in adverse conditions.

  7. Extending WireMock: WireMock has a high degree of customizability and extensibility, allowing you to develop custom request matches, response transformations, and other cool extensions in Java or JS.

Here is a brief visualization of how the WireMock HTTP server intercepts requests and can forward them to the necessary stub, or to the actual service.

Do I service mesh or stub?

Does this replace the functionality of a service mesh? ABSOLUTELY NOT! A service mesh is still the foundational layer for routing requests, service-to-service encryption, and telemetry.

This is important because while you are still deploying services and meshing them with a service mesh like Istio, the need to continually test for application behaviour will be required. Using a simple "httpbin" service might help tell part of the story but, customizing responses is far more powerful, and this is a key function of WireMock.

Next up…

In the next few posts, we’ll continue to explore application testing by deploying Istio and the WireMock HTTP server to Kubernetes to assess simple responses. We’ll also explore chaos testing with WireMock and the Istio Service Mesh and how this can ready us for production.

Interested in learning more about stubbing? Head over to WireMock.org for more details. Also, feel free to join the WireMock community in Slack! Looking for something beyond open source - hosted solution, and user interface for a quick and easy start?? Check out WireMock Cloud!!!

Want to get meshy with Service Mesh, Kubernetes and Istio? Head over to Istio.io!

Thank you for reading :)