mocktail is a minimal framework for mocking HTTP and gRPC services in Rust with support for streaming.
- Mocks HTTP and gRPC servers
- Mocks defined in Rust using a simple API
- Supports HTTP streaming
- Supports gRPC unary, client-streaming, server-streaming, and bidirectional-streaming methods
- Performs basic "full body" (equals) matching
A server that handles mock requests. This crate contains 2 servers:
- HttpMockServer
- GrpcMockServer
- Not used directly, implementations are generated via
generate_grpc_server!
macro
- Not used directly, implementations are generated via
An enum containing the bytes of a mock request or response body.
pub enum MockBody {
Empty,
Full(Bytes),
Stream(Vec<Bytes>),
}
A mock request containing an optional body and optional headers.
// An empty body
MockRequest::empty()
// With a body that implements `Into<Bytes>`
MockRequest::new(body)
MockRequest::stream(messages)
// Convenience constructors:
// JSON: with a body that implements `serde::Serialize`
MockRequest::json(body)
MockRequest::json_stream(messages)
// Protobuf (gRPC): with a body that implements `prost::Message`
MockRequest::pb(body)
MockRequest::pb_stream(messages)
A mock response containing a response code, optional body, optional headers, and optional error message. The response code defaults to 200
.
// An empty body
MockResponse::empty()
// With a body that implements `Into<Bytes>`
MockResponse::new(body)
MockResponse::stream(messages)
// Convenience constructors:
// JSON: with a body that implements `serde::Serialize`
MockResponse::json(body)
MockResponse::json_stream(messages)
// Protobuf (gRPC): with a body that implements `prost::Message`
MockResponse::pb(body)
MockResponse::pb_stream(messages)
A mock request and response pair.
A mock path for request matching.
A set of mocks for a service.
-
Add
mocktail
toCargo.toml
as a development dependency:[dev-dependencies] mocktail = "0.1.0-alpha"
-
In a test context, use as follows. See mocktail-test crate for more usage examples.
use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct HelloRequest { pub name: String, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct HelloResponse { pub message: String, } #[cfg(test)] mod tests { use super::*; use mocktail::prelude::*; #[tokio::test] async fn test_hello_simple() -> Result<(), Box<dyn std::error::Error>> { // Create a mock set. let mut mocks = MockSet::new(); // Insert mocks. // `MockRequest::json()` and `MockResponse::json()` are convenience methods // that handle JSON serialization to avoid `serde_json::to_vec(&value)` boilerplate. mocks.insert( MockPath::new(Method::POST, "/hello"), Mock::new( MockRequest::json(HelloRequest { name: "World".into() }), MockResponse::json(HelloResponse { message: "Hello World!".into(), }), ), ); // Create and start a mock server. let server = HttpMockServer::new("hello", mocks)?; server.start().await?; // Send request to mock server. let client = reqwest::Client::new(); let response = client .post(server.url("/hello")) .json(&HelloRequest { name: "World".into() }) .send() .await?; assert!(response.status() == StatusCode::OK); let body = response.json::<HelloResponse>().await?; dbg!(&body); // Send request to mock server. // Doesn't match a mock so should return an error. let client = reqwest::Client::new(); let response = client .post(server.url("/hello")) .json(&HelloRequest { name: "Missing".into(), }) .send() .await?; assert!(response.status() == StatusCode::NOT_FOUND); Ok(()) } }
See mocktail-test crate.