HTTP mocking library for Rust.
Documentation · Crate · Report Bug · Request Feature
Add httpmock
to Cargo.toml
:
toml
[dev-dependencies]
httpmock = "0.4.2"
You can then use httpmock
in your tests like shown in the example below:
```rust
extern crate httpmock;
use httpmock::Method::{GET}; use httpmock::{Mock, MockServer, MockServerRequest, Regex};
fn exampletest() { // Arrange: Create a mock on a local mock server let mockserver = MockServer::start();
let search_mock = Mock::new()
.expect_method(GET)
.expect_path("/search")
.return_status(200)
.create_on(&mock_server);
// Act: Send an HTTP request to the mock server (simulates your software)
let url = format!("http://{}/search", mock_server.address());
let response = isahc::get(&url).unwrap();
// Assert: Ensure there was a response from the mock server
assert_eq!(response.status(), 200);
assert_eq!(search_mock.times_called(), 1);
} ```
Each test usually creates its own local MockServer
using MockServer::start()
. This creates a lightweight HTTP
server that runs on its own port. This way tests do not conflict with each other.
You can use the Mock
structure to specify and create mocks on the mock server. It provides you all supported mocking
functionality.
Other than many other libraries httpmock
does not require you to learn a DSL-like API to
specify mock behaviour. Instead, httpmock
provides you a fluent builder API that
clearly separates request matching and response attributes by using the following naming scheme:
Mock
methods that start with expect
in their name set a requirement
for HTTP requests (e.g. Mock::expect_method
, Mock::expect_path
, or Mock::expect_body
).Mock
methods that start with return
in their name define what the
mock server will return in response to an HTTP request that matched all mock requirements (e.g.
Mock::return_status
, Mock::return_body
, etc.).With this naming scheme users can benefit from IDE autocompletion to find request matchers and response attributes mostly without even looking into documentation.
If a request does not match at least one mock, the server will respond with an error message and HTTP status code 404 (Not Found).
The internal implementation of httpmock
is fully 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
and Mock::create_on_async
for Mock::create_on
.
To balance execution speed and resource consumption, MockServer
s are kept in a server pool internally. This allows to run multiple 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::new()
) while the server pool is empty (i.e. all servers are occupied by other tests). To avoid TCP port binding issues, MockServers
are never recreated but recycled/resetted. The pool is filled on demand up to a predefined maximum number of 25 servers. You can change this number by setting the environment variable HTTPMOCK_MAX_SERVERS
.
Fore more examples, please refer to this crates test directory.
httpmock
logs against the log
crate. For example, if you use the env_logger
backend, you can activate debug logging by setting the RUST_LOG
environment variable to httpmock=debug
.
You can use httpmock
to run a standalone mock server that is available to multiple applications. This can be useful if you are running integration tests that involve both, real and mocked applications.
Altough you can build the mock server in standalone mode yourself, it is easiest to use the Docker image from the accompanying Docker image. Please refer to the documentation on Docker repository.
To be able to use a standalone server from your tests, you need to change how an instance of the MockServer
structure is created. Instead of using MockServer::new()
, you need to connect to a remote server by using one of the connect
methods (such as MockServer::connect("localhost:5000")
or MockServer::connect_from_env()
). Therefore, tests that use a local mock server do only differ in one line of code from tests that use a remote server. Otherwise, both variants are identical.
```Rust
fn simpletest() { // Arrange: Create a mock on a test local mock server let mockserver = MockServer::connect("some-host:5000");
let search_mock = Mock::new()
.expect_method(GET)
.expect_path("/search")
.return_status(200)
.create_on(&mock_server);
// Act: Send an HTTP request to the mock server (simulates your software)
let url = format!("http://{}/search", mock_server.address())).unwrap();
let response = http_get(&url).unwrap();
// Assert: Ensure there was a response from the mock server
assert_eq!(response.status(), 200);
assert_eq!(search_mock.times_called(), 1);
} ```
Tests that use a remote mock server are executed sequentially by default. This is in contrast to tests that use a local mock server. Sequential execution is achieved by blocking all tests from further execution whenever a test requires to connect to a busy mock server.
At this time, it is not possible to use custom request matchers in combination with remote mock servers. It is planned to add this functionality in future though.
Fore more examples on how to use a remote server, please refer to this crates test directory.
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.