Skip to content

Fundamental Concepts

Why Mocking HTTP Services?

Many applications rely on HTTP-based endpoints like REST APIs. During testing, developers often mock HTTP communication to avoid external dependencies. This is typically done by replacing the real HTTP client with a test-specific stub, allowing tests to focus on internal logic without executing actual HTTP requests.

However, this approach leaves a significant portion of the client code untested, including whether it sends correct HTTP requests and is able to handle real HTTP responses, network issues, or error responses.

httpmock bridges this gap by letting your tests use real client code to send requests to a mock server instead of the actual service. The mock server is set up to respond according to the specific needs of each test scenario.

Mocking Basics

httpmock allows you to configure mock servers for a test scenario by calling its mock method:

let server = httpmock::MockServer::start();
let mock = server.mock(|when, then| {
when.path("/hello");
then.status(200);
});

The mock method creates a rule on the mock server that responds to HTTP requests when the request marches all specified criteria.

The when variable is a builder-like structure that specifies when the mock server should respond. In the example, it is configured to respond to requests with the path /hello (e.g., GET http://localhost:8080/hello). Since no additional criteria are provided, the mock server will respond to any request with the path /hello, regardless of the HTTP method (e.g., GET, POST) or request body content.

The then variable specifies the response details when a request meets the defined criteria. In the example, it sets the response to return a status code 200 (OK) without body, headers, or any other value.

If a request does not meet all specified criteria, the mock server will automatically respond with status code 404 (Not Found).

There is no limit to the number of mocks you can create on a mock server. You can set up as many as needed for your test scenarios.

Sync and Async API

The internal implementation of httpmock is entirely based on asynchronous communication. However, it provides both, a synchronous (blocking) and an asynchronous (non-blocking) API. Asynchronous operations can be identified by the API’s method signatures, typically ending with _async (such as mock_async as the asynchronous variant of the method mock). This pattern can be found throughout the entire API of httpmock.

Supported Async Executors

httpmock is designed to be executor-agnostic. Our CI/CD pipeline includes dedicated tests to verify compatibility with at least the following async executors:

Test Execution and Pooling

When you initialize MockServer instances in your tests (e.g., using MockServer::start()), httpmock allocates a mock server from a global server pool for exclusive use by your test. This ensures that no other test can use the same mock server instance during test execution.

Once the test ends, either successfully or with a failure, the mock server instance is automatically returned to the global pool and made available for other tests. The library automatically manages all cleanup of the mock server.

The default pool limit is set at 25 mock servers to avoid overloading the host system. Although this limit is conservative, many host machines can handle additional servers. Increasing this limit may not be necessary, depending on the parallelism settings of your test execution. You can modify the pool size by setting the HTTPMOCK_MAX_SERVERS environment variable.

When the global mock server pool is empty and all servers are in use, any test attempting to instantiate a mock server will automatically be blocked until a server becomes available again.

Parallelism With Remote Mock Servers

httpmock allows mock servers to be executed in standalone mode, where each server runs in its own process, typically launched as a separate binary. Tests can connect to these “remote” mock servers using MockServer::connect, MockServer::connect_async, and other MockServer functions prefixed with connect.

When using any connect function in tests, the parallelism is set to 1, allowing only one test to access the remote server at a time. This ensures that there are no conflicts with other tests during execution.

Environment Variables

Rust Tests

  • HTTPMOCK_MAX_SERVERS: Sets the maximum number of mock servers in the global mock server pool.
  • HTTPMOCK_REQUEST_HISTORY_LIMIT: Mock servers keep a history of all requests that have been received in a test. The history works like a ring buffer, removing the oldest request from the history once it reaches the configured maximum. The request history is used for call assertions to verify that a request has been received that matches certain criteria, such as in Mock::assert. By default, this number is set to 100.
  • HTTPMOCK_HOST / HTTPMOCK_PORT: Sets the hostname/port that should be used connect to remote mock servers when using MockServer::connect_from_env() or MockServer::connect_from_env_async().

Standalone Binary:

  • HTTPMOCK_EXPOSE: If set to 1, the mock server will be configured to accept external connections (binds to 0.0.0.0). Otherwise, only connections from your local machine will be accepted.
  • HTTPMOCK_MOCK_FILES_DIR: The location where the mock server should look for mock definition files (YAML format).
  • HTTPMOCK_DISABLE_ACCESS_LOG: When set to 0, the mock server will not log incoming requests.

Cargo Features

The crate provides the following Cargo features:

  • cookies: Enables request matchers for parsing and matching values in cookies
  • proxy: Enables the mock server to function as a proxy server
  • record: Enables functionality to record requests and responses (most useful in combination with the proxy feature). Enables reading mock specifications from YAML files (e.g., recorded responses)
  • https: Enables the mock server to provide a unified port for both, HTTP and HTTPS. Attention: This feature is experimental. Hence, there are no guarantees that this feature will work.
  • http2: Enables mock server support for HTTP2
  • standalone: Enables standalone mode
  • remote: Allows to connect to remote (standalone) mock servers
  • remote-https: Enables communication to remote (standalone) mock servers via HTTPS
  • color: enables colorful output in standalone mode

For example, the command cargo test --features=remote enables the functionality in your tests to communicate with remote standalone mock servers.