Skip to content

IBM/mocktail

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

mocktail

mocktail is a minimal framework for mocking HTTP and gRPC services in Rust with support for streaming.

Table of contents

Features

  • 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

Concepts

Mock Server

A server that handles mock requests. This crate contains 2 servers:

  • HttpMockServer
  • GrpcMockServer
    • Not used directly, implementations are generated via generate_grpc_server! macro

Mock Body

An enum containing the bytes of a mock request or response body.

pub enum MockBody {
    Empty,
    Full(Bytes),
    Stream(Vec<Bytes>),
}

Mock Request

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)

Mock Response

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)

Mock

A mock request and response pair.

Mock Path

A mock path for request matching.

Mock Set

A set of mocks for a service.

Usage

  1. Add mocktail to Cargo.toml as a development dependency:

    [dev-dependencies]
    mocktail = "0.1.0-alpha"
  2. 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(())
        }
    }

Examples

See mocktail-test crate.

About

HTTP & gRPC server mocking for Rust

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages