Overview

Get started today
Replay past traffic, gain confidence in optimizations, and elevate performance.

Why use MockServer to mock APIs?

As the name suggests, MockServer is a powerful tool that allows developers to mock HTTP APIs, making it much easier and more efficient to run an integration test in initial development phases. It aims to solve the problem of testing APIs that are still in development or not yet available, allowing developers to make http calls on an http client without a real server.

While there are other popular mocking tools available, such as WireMock and Pact, MockServer stands out for its focus on providing a quick and easy mock solution that’s supported in most major programming languages and technologies.

This post will cover step-by-step instructions on how to use MockServer to mock an HTTP API, as well as an overview of any limitations you might encounter. It’s important to note that while MockServer is a great tool, it may not be the best fit for every use case. This post intends to present a great use case for MockServer, but remember to evaluate for yourself and your unique scenario.

MockServer with and without Mock API

What is MockServer?

A mock server is designed to simulate external HTTP APIs (REST API, RPC service, etc.) through a mock, proxy, or both. By letting an http client invoke real http calls, a mock server speeds up the initial development phases without needing a real server. MockServer stands out from other mocking tools due to its impressive range of deployment options. Just in Java, you can mock server endpoints through test assertions like a JUnit 4 @Rule, a JUnit 5 Test Extension, or a Spring Test Execution Listener, so MockServer can fit into a variety of workflows.

The versatility and adaptability of MockServer set it apart from its peers. No matter the environment – be it your local machine, Docker-enabled, or Kubernetes, MockServer likely integrates well into your infrastructure. Its compatibility with popular build tools like Maven and Grunt and the ability to be used programmatically through Java or Node.js makes it applicable in a variety of testing scenarios.

It’s an excellent choice when you want to keep things local or need a tool that can be worked directly into the code regardless of the language you’re using.

A mock server diagram

Skip the scripts and large test environments with Speedscale’s service virtualization

How to mock HTTP APIs

Aiming to provide value to as many as possible, this tutorial will use one of the language-agnostic options: docker-compose. MockServer will be used to establish a mock HTTP API for a hypothetical online game platform. This platform offers a RESTful API that game developers use to fetch player statistics, update game scores, and manage in-game purchases. Our objective is to replicate this API’s behavior with MockServer, allowing us to test the client-side interactions independently, without requiring a connection to the actual game platform’s servers.

Configure expectations using JSON initializer

In the MockServer ecosystem, request/response pairs are referred to as Expectations, which are test assertions written as Java or JavaScript code, or, you can define them in a JSON file—which is what you’ll do now. This approach allows you to separate your mock definitions from your code, making them easier to maintain and reuse, especially across projects. 

Create an initializer.json file in your current directory with the following content:

				
					[
  {
    "httpRequest": {
      "method": "GET",
      "path": "/player/stats",
      "queryStringParameters": {
        "playerId": ["1234"]
      }
    },
    "httpResponse": {
      "statusCode": 200,
      "body": "{\"playerId\": \"1234\",\"gamesPlayed\": 57,\"averageScore\": 3200,\"topScore\": 5600}",
      "headers": {
        "Content-Type": ["application/json"]
      }
    }
  }
]
				
			

This JSON file declares an expectation for a GET request to /player/stats with a playerId query parameter. When this request is received, the server responds with a 200 status code and a JSON body containing some made-up player statistics.

Set up MockServer using Docker-Compose

With the expectations defined you can now spin up the MockServer using docker-compose. Docker-compose may not be strictly necessary in this case as it’s only one container, however, it helps provide a clear and approachable overview of container configurations.

Create a docker-compose.yaml file with the following content:

				
					version: '3'
services:
  mockServer:
    image: mockserver/mockserver:latest
    ports:
      - 1080:1080
    volumes:
      - ./initializer.json:/config/initializer.json
    environment:
      MOCKSERVER_INITIALIZATION_JSON_PATH: /config/initializer.json

				
			

This configuration exposes the MockServer on port 1080 and mounts the initializer.json file from your current directory into the /config directory inside the container, which the environment variable MOCKSERVER_INITIALIZATION_JSON_PATH points to so MockServer can load your expectations from it.

To start the MockServer container, run docker-compose up -d which will start the MockServer in the background.

Interacting with the mock

Once MockServer is configured and running, interacting with the mock API is very similar to interacting with any other RESTful API. Given that you’ve only set up an expectation for a “GET” request to /player/stats endpoint with a playerId of 1234, let’s test that on your local machine.

Get a response from the mock API by running:

				
					curl "http://localhost:1080/player/stats?playerId=1234"
				
			

Barring any bugs, you should see a response like above, which would indicate a successful mock implementation. However, MockServer does provide a better way of verifying mock API interactions.

Verify requests

Verification is used to ensure that the MockServer received a specific request. For instance, after running some tests, you might want to verify that your client sent a GET request to fetch player stats:

				
					curl -v -X PUT "http://localhost:1080/mockserver/verify" -d '{
    "httpRequest": {
        "method": "GET",
        "path": "/player/stats",
        "queryStringParameters": {
            "playerId": ["1234"]
        }
    },
    "times": {
        "atLeast": 1,
        "atMost": 1,
    }
}'

				
			

This code verifies that the MockServer received exactly one GET request to /player/stats for the player with id 1234.

And there you have it! You’ve successfully utilized MockServer with docker-compose and JSON configuration to mock an HTTP API.

Scales

A developer’s guide to continuous performance testing

The limitations of MockServer

While MockServer is a powerful tool for testing and developing applications, it’s important to be aware of its limitations. Here are some aspects you should consider when deciding if MockServer is the right solution for your project.

Limited support for non-HTTP protocols

MockServer has been primarily designed to handle HTTP and HTTPS requests, which makes it a versatile tool for testing web applications. However, when it comes to non-HTTP protocols, its capabilities become limited. For example, protocols such as gRPC and WebSocket, which are widely used in real-time applications, are not supported in MockServer. This could be a significant limitation if your application heavily relies on these real-time, bidirectional communication protocols.

Furthermore, while MockServer allows for updating expectations on-the-fly, its support for real-time updates and feedback during testing is not as robust as some might wish. This becomes particularly relevant in scenarios that require rapid adjustment of expectations based on ongoing test results or changing application states.

For instance, testing a system that needs to adapt to fluctuating network conditions or user loads would necessitate a tool that can accurately simulate these real-world behaviors. Unfortunately, MockServer’s real-time adaptation capabilities are currently limited.

Possible technical and human performance overhead

MockServer does provide some basic templating and dynamic response capabilities, but these might not suffice for more complex, data-driven scenarios. For instance, if your use case involves crafting intricate responses based on specific request parameters, or if you require random data generation for chaos testing, you might find the tool’s capabilities restrictive, which may mean you need to resort to additional programming or scripting to achieve the desired level of dynamism in your responses.

Coupling this with the performance overhead that MockServer might introduce, especially when dealing with a large number of tests or high request volumes, you have a two-fold challenge. While MockServer is highly efficient, the fact that it runs as a separate external process means that it does consume additional resources. In scenarios where hundreds or even thousands of tests are run concurrently, this overhead could potentially impact the application’s performance during testing.

In fairness to MockServer, this is true for any mock or load generation tool. However, MockServer comes with few infrastructure optimizations, handing over that responsibility to you.

Limited traffic shaping capabilities

One of the challenges when using MockServer is its limited traffic shaping capabilities. Traffic shaping is the process of controlling the speed, volume, and nature of network traffic. It’s a valuable technique when trying to simulate real-world network conditions for applications, such as latency, packet loss, or bandwidth limits. Unfortunately, MockServer doesn’t inherently provide these features.

While you can delay responses in MockServer to simulate network latency, the functionality doesn’t extend much beyond that. For instance, it lacks native support for simulating different network qualities, such as 3G or 4G, or varying conditions, such as congested networks.

You’d need to resort to additional tooling or potentially complex workarounds to replicate these conditions effectively. This limitation may pose challenges in accurately simulating real-world scenarios or conducting comprehensive performance testing. This is of course before mentioning how some tools are moving away from traffic shaping, favoring production traffic replication instead.

Limited built-in monitoring and analytics

Monitoring and analytics are crucial aspects of API testing and development. They provide insights into the performance, usage, and potential issues of your APIs. However, MockServer provides limited built-in monitoring and analytics features, as seen with the /verify endpoint from earlier.

While MockServer does log all interactions, including setting up expectations, matching expectations, clearing expectations, and verifying requests, these logs might not be sufficient for deeper analysis or long-term monitoring. For example, you might want to monitor the rate of specific types of requests, track response times over time, or analyze usage trends for capacity planning. These advanced analytics capabilities are not natively available in MockServer.

While you can extract some of this information from the logs, doing so can be time-consuming and might require additional tooling or processing. Without a robust, built-in analytics solution, diagnosing issues, optimizing performance, or gaining insights into your API’s usage can be more challenging.

Align the tool with your use case

In conclusion, this post has provided a comprehensive guide on how to use MockServer to mock HTTP APIs, with a focus on an intriguing example of an online game platform’s RESTful API. MockServer can be used to effectively isolate client-side interactions for testing, with minimal dependency on actual server availability. However, while MockServer is a powerful tool, it’s important to consider its limitations as a mock server. If simulating complex scenarios or real-world network conditions, a different mock server might be better for your integration test.

For instance, while MockServer does support deployment in Kubernetes, you may be overwhelmed by the additional infrastructure management it requires. Instead, you’ll want to research other possible ways of mocking APIs in Kubernetes.

Learn more about service virtualization

PRODUCT

Automatically mock dependencies: service mocking with Speedscale

BLOG

Tests, data & dependencies: defeating the triple threat of software testing

Ensure performance of your Kubernetes apps at scale

Auto generate load tests, environments, and data with sanitized user traffic—and reduce manual effort by 80%
Start your free 30-day trial today