Crate httpmock[][src]

HTTP mocking library that allows you to simulate responses from HTTP based services.

Features

  • Simple, expressive, fluent API.
  • Many built-in helpers for easy request matching.
  • Parallel test execution.
  • Extensible request matching.
  • Fully asynchronous core with synchronous and asynchronous APIs.
  • Debugging support
  • Standalone mode with an accompanying Docker image.
  • Network delay simulation
  • Support for Regex matching, JSON, serde, cookies, and more.

Getting Started

Add httpmock to Cargo.toml:

[dev-dependencies]
httpmock = "0.5.5"

You can then use httpmock as follows:

use httpmock::MockServer;
use httpmock::Method::GET;

// Start a lightweight mock server.
let server = MockServer::start();

// Create a mock on the server.
let hello_mock = server.mock(|when, then| {
    when.method(GET)
        .path("/translate")
        .query_param("word", "hello");
    then.status(200)
        .header("Content-Type", "text/html")
        .body("ohi");
});

// Send an HTTP request to the mock server. This simulates your code.
let response = isahc::get(server.url("/translate?word=hello")).unwrap();

// Ensure the specified mock was called exactly one time (or fail with a detailed error description).
hello_mock.assert();
// Ensure the mock server did respond as specified.
assert_eq!(response.status(), 200);

Usage

To be able to configure mocks, you first need to start a mock server by calling MockServer::start. This will spin up a lightweight HTTP mock server in the background and wait until the server is ready to accept requests.

You can then create a Mock object on the server by using the MockServer::mock method. This method expects a closure with two parameters, that we will refer to as the when and then parameter:

  • The when parameter is of type When and holds all request characteristics. The mock server will only respond to HTTP requests that meet all the criteria. Otherwise it will respond with HTTP status code 404 and an error message.
  • The then parameter is of type Then and holds all values that the mock server will respond with.

Sync / Async

The internal implementation of httpmock is completely asynchronous. It provides you a synchronous and an asynchronous API though. If you want to schedule awaiting operations manually, then you can use the async variants that exist for every potentially blocking operation. For example, there is MockServer::start_async as an asynchronous counterpart to MockServer::start. You can find similar methods throughout the entire library.

Parallelism

To balance execution speed and resource consumption, MockServers are kept in a server pool internally. This allows to run tests in parallel without overwhelming the executing machine by creating too many HTTP servers. A test will be blocked if it tries to use a MockServer (e.g. by calling MockServer::start) while the server pool is empty (i.e. all servers are occupied by other tests).

MockServers are never recreated but recycled/resetted. The pool is filled on demand up to a maximum number of 25 servers. You can override this number by using the environment variable HTTPMOCK_MAX_SERVERS.

Debugging

httpmock logs against the log crate. This allows you to see detailed log output that contains information about httpmocks behaviour. You can use this log output to investigate issues, such as to find out why a request does not match a mock definition.

The most useful log level is debug, but you can also go down to trace to see even more information.

Attention: To be able to see the log output, you need to add the --nocapture argument when starting test execution!

Hint: If you use the env_logger backend, you need to set the RUST_LOG environment variable to httpmock=debug.

API Alternatives

This library provides two functionally interchangeable DSL APIs that allow you to create mocks on the server. You can choose the one you like best or use both side-by-side. For a consistent look, it is recommended to stick to one of them, though.

When/Then API

This is the default API of httpmock. It is concise and easy to read. The main goal is to reduce overhead emposed by this library to a bare minimum. It works well with formatting tools, such as rustfmt (i.e. cargo fmt), and can fully benefit from IDE support.

Example

let server = httpmock::MockServer::start();

let greeting_mock = server.mock(|when, then| {
    when.path("/hi");
    then.status(200);
});

let response = isahc::get(server.url("/hi")).unwrap();

greeting_mock.assert();

Note that when and then are variables. This allows you to rename them to something you like better (such as expect/respond_with).

Relevant elements for this API are MockServer::mock, When and Then.

Examples

You can find examples in the test directory in this crates Git repository: this crates test directory.

Standalone Mode

You can use httpmock to run a standalone mock server that runs in a separate process. This allows it to be available to multiple applications, not only inside your unit and integration tests. This is useful if you want to use httpmock in system (or even end-to-end) tests, that require mocked services. With this feature, httpmock is a universal HTTP mocking tool that is useful in all stages of the development lifecycle.

Using a Standalone Mock Server

Although you can build the mock server in standalone mode yourself, it is easiest to use the accompanying Docker image.

To be able to use the standalone server from within your tests, you need to change how an instance of the MockServer instance is created. Instead of using MockServer::start, you need to connect to a remote server by using one of the connect methods (such as MockServer::connect or MockServer::connect_from_env).

use httpmock::{MockServer, Mock};
use isahc::get;

#[test]
fn simple_test() {
    // Arrange
    let server = MockServer::connect("some-host:5000");

    let hello_mock = server.mock(|when, then|{
        when.path("/hello/standalone");
        then.status(200);
    });

    // Act
    let response = get(server.url("/hello/standalone")).unwrap();

    // Assert
    hello_mock.assert();
    assert_eq!(response.status(), 200);
}

Standalone Parallelism

To prevent interference with other tests, test functions are forced to use the standalone mock server sequentially. This means that test functions may be blocked when connecting to the remote server until it becomes free again. This is in contrast to tests that use a local mock server.

Limitations of the Standalone Mode

At this time, it is not possible to use custom request matchers in combination with standalone mock servers (see When::matches or Mock::expect_match).

License

httpmock is free software: you can redistribute it and/or modify it under the terms of the MIT Public License.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MIT Public License for more details.

Modules

standalone

Structs

HttpMockRequest

A general abstraction of an HTTP request of httpmock.

MockDeprecated

The Mock structure holds a definition for a request/response scenario that can be used to configure a MockServer.

MockRef

Represents a reference to the mock object on a MockServer. It can be used to spy on the mock and also perform some management operations, such as deleting the mock from the MockServer.

MockServer

A mock server that is able to receive and respond to HTTP requests.

Then

A type that allows the specification of HTTP response values.

When

A type that allows the specification of HTTP request values.

Enums

Method

Represents an HTTP method.

Traits

MockRefExt

The MockRefExt trait extends the MockRef structure with some additional functionality, that is usually not required.

Type Definitions

MockMatcherFunction
Regex

Type alias for regex::Regex.