Mocking HTTP clients is essential for testing your application's logic without making actual HTTP requests. This can speed up your tests and make them more reliable, as they won't depend on external services. For Rust, if you're using the reqwest
crate for making HTTP requests, you can use the mockito
crate for mocking those requests in your tests.
Here's how to set up and use mockito
with reqwest
:
- Add
mockito
to yourCargo.toml
along withreqwest
if you haven't already:
[dependencies]
reqwest = "0.11"
mockito = "0.30"
tokio = { version = "1", features = ["full"] }
- Write a test using
mockito
to mock an HTTP service:
#[cfg(test)]
mod tests {
use mockito::{mock, Matcher};
use reqwest;
#[tokio::test]
async fn test_get_request() {
// Start a mock server and return a mock response when the endpoint is hit
let _m = mock("GET", "/some-endpoint")
.with_status(200)
.with_header("content-type", "text/plain")
.with_body("mocked response")
.create();
// Use reqwest to make a request to the mock server
let client = reqwest::Client::new();
let response = client
.get(&format!("{}/some-endpoint", &mockito::server_url()))
.send()
.await
.unwrap();
// Check that the response is what you've mocked
assert_eq!(response.status(), reqwest::StatusCode::OK);
let body = response.text().await.unwrap();
assert_eq!(body, "mocked response");
// The mock goes out of scope and asserts that it matched exactly one request
}
}
Note: The above example assumes you're using tokio
as the async runtime and reqwest
version 0.11
. Adjust the version numbers according to your project's setup.
The mockito
crate provides a convenient way to set up your expectations for the mock service, including the expected HTTP method, path, headers, and response body. When the reqwest
client makes a request that matches these expectations, mockito
will serve the mocked response back to the client.
In the example, we create a mock with the path /some-endpoint
, expecting a GET
request. When the test runs, it starts a mock server that listens for incoming requests and provides the specified mock response. We then make a request using reqwest
to the URL provided by mockito::server_url()
, which points to the mock server.
When the mock goes out of scope, mockito
will assert that it matched exactly one request. If the number of requests doesn't match your expectations, the test will fail, helping you ensure that your application is making the correct HTTP calls.
Remember that mocking is just one part of testing. You should also have integration tests that make real HTTP requests to a test server to ensure end-to-end functionality. Mock tests are valuable for testing logic in isolation and when you want to simulate different response scenarios from an external service.