1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
//! # wiremock-grpc
//!
//! gRPC mocking to test Rust applications.
//!
//! This crate provides an easy way to mock gRPC services in your tests, allowing you to
//! test client code without running actual gRPC servers. It features a type-safe API
//! for defining mock behaviors and verifying requests.
//!
//! ## Quick Start
//!
//! Use the [`generate_svc!`] macro to create a mock server:
//!
//! ```no_run
//! use wiremock_grpc::{generate_svc, MockBuilder};
//! use tonic::Code;
//! # mod hello {
//! # pub mod greeter_client {
//! # pub struct GreeterClient<T>(T);
//! # impl<T> GreeterClient<T> {
//! # pub fn new(t: T) -> Self { Self(t) }
//! # pub async fn say_hello(&mut self, _req: super::HelloRequest)
//! # -> Result<tonic::Response<super::HelloReply>, tonic::Status> {
//! # Ok(tonic::Response::new(super::HelloReply { message: "".into() }))
//! # }
//! # }
//! # }
//! # pub use greeter_client::GreeterClient;
//! # #[derive(Clone, PartialEq, prost::Message)]
//! # pub struct HelloRequest { #[prost(string, tag = "1")] pub name: String }
//! # #[derive(Clone, PartialEq, prost::Message)]
//! # pub struct HelloReply { #[prost(string, tag = "1")] pub message: String }
//! # }
//! # use hello::{GreeterClient, HelloRequest, HelloReply};
//!
//! // Generate a mock server (make sure the package, service and the rpc names are exactly as they are named in the proto files)
//! generate_svc! {
//! package hello;
//! service Greeter {
//! SayHello,
//! WeatherInfo,
//! }
//! }
//!
//! #[tokio::test]
//! async fn test_grpc_service() {
//! // Start the mock server
//! let mut server = GreeterMockServer::start_default().await;
//!
//! // Set up a mock response
//! server.setup(
//! MockBuilder::when()
//! .path_say_hello() // method generated by generate_svc macro (for each item under "service" block)
//! .then()
//! .return_status(Code::Ok)
//! .return_body(|| HelloReply {
//! message: "Hello from mock!".into(),
//! }),
//! );
//!
//! // Connect your client and test
//! let channel = tonic::transport::Channel::from_shared(
//! format!("http://[::1]:{}", server.address().port())
//! )
//! .unwrap()
//! .connect()
//! .await
//! .unwrap();
//!
//! let mut client = GreeterClient::new(channel);
//! let response = client
//! .say_hello(HelloRequest { name: "World".into() })
//! .await
//! .unwrap();
//!
//! assert_eq!("Hello from mock!", response.into_inner().message);
//! }
//! ```
//!
//! ## Features
//!
//! - **Type-safe API**: Generate type-safe `path_*` methods for each RPC using [`generate_svc!`]
//! - **Header Matching**: Match requests based on gRPC metadata/headers
//! - **Status Codes**: Return any gRPC status code
//! - **Custom Bodies**: Return custom response bodies with closures
//! - **Request Verification**: Track invocations and verify calls were made
//! - **Flexible Binding**: Start servers on random ports, specific ports, or custom addresses
//!
//! ## Custom Server Name
//!
//! You can specify a custom name for the generated server:
//!
//! ```no_run
//! # use wiremock_grpc::generate_svc;
//! generate_svc! {
//! package hello;
//! service Greeter as MyCustomServer {
//! SayHello,
//! }
//! }
//! # async fn example() {
//! let server = MyCustomServer::start_default().await;
//! # }
//! ```
//!
//! ## Header Matching
//!
//! Match requests based on gRPC metadata:
//!
//! ```no_run
//! # use wiremock_grpc::{generate_svc, MockBuilder, Then};
//! # generate_svc! { package hello; service Greeter { SayHello } }
//! # #[derive(Clone, PartialEq, prost::Message)]
//! # struct HelloReply { #[prost(string, tag = "1")] message: String }
//! # async fn example(mut server: GreeterMockServer) {
//! server.setup(
//! MockBuilder::when()
//! .path_say_hello()
//! .header("x-session-id", "abc123")
//! .then()
//! .return_body(|| HelloReply {
//! message: "Authenticated response".into(),
//! }),
//! );
//! # }
//! ```
//!
//! ## What [`generate_svc!`] Generates
//!
//! The macro generates:
//! - `{ServiceName}MockServer` - Mock server struct with:
//! - `start_default()` - Start on a random available port
//! - `start(port)` - Start on a specific port
//! - `start_with_addr(addr)` - Start on a specific address
//! - `setup()` - Configure mock behaviors
//! - `address()` - Get the server's bind address
//! - `{ServiceName}TypeSafeExt` - Extension trait adding `path_{method_name}` methods to [`WhenBuilder`]
//!
//! ## Main Types
//!
//! - [`MockBuilder`] - Build mock behaviors with `when()` and `then()` pattern
//! - [`WhenBuilder`] - Configure request matching (path, headers, etc.)
//! - [`Then`] - Configure response behavior (status, body, headers)
//! - [`GrpcServer`] - The underlying mock server (dereferenced by generated servers)
pub use ;
pub use GrpcServer;
pub use tonic_ext;
pub use generate_svc;
pub extern crate http_body;
pub extern crate tonic;