Skip to content

Commit 9c6e350

Browse files
authored
0.1.2 alpha (#3)
* grpc: fix error mock handling Signed-off-by: declark1 <[email protected]> * Add support for header matching (wip), other tweaks Signed-off-by: declark1 <[email protected]> --------- Signed-off-by: declark1 <[email protected]>
1 parent d5728c3 commit 9c6e350

16 files changed

+268
-119
lines changed

Cargo.lock

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

mocktail-test/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mocktail-test"
3-
version = "0.1.1-alpha"
3+
version = "0.1.2-alpha"
44
edition = "2021"
55
authors = ["Dan Clark", "Gaurav Kumbhat"]
66

mocktail-test/src/grpc_health.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ mod tests {
1313
async fn test_health() -> Result<(), anyhow::Error> {
1414
let mut mocks = MockSet::new();
1515
mocks.insert(
16-
MockPath::new(Method::POST, "/grpc.health.v1.Health/Check"),
16+
MockPath::post("/grpc.health.v1.Health/Check"),
1717
Mock::new(
1818
MockRequest::pb(HealthCheckRequest { service: "".into() }),
1919
MockResponse::pb(HealthCheckResponse { status: 1 }),

mocktail-test/src/grpc_hello.rs

+60-10
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,52 @@ mod pb {
66
mod tests {
77
use std::time::Duration;
88

9-
use futures::{StreamExt, stream};
9+
use futures::{stream, StreamExt};
1010
use mocktail::prelude::*;
1111
use tokio_stream::wrappers::ReceiverStream;
1212
use tonic::transport::Channel;
1313
use tracing::debug;
1414

15-
use super::pb::{HelloRequest, HelloResponse, hello_client::HelloClient};
15+
use super::pb::{hello_client::HelloClient, HelloRequest, HelloResponse};
1616

1717
#[test_log::test(tokio::test)]
1818
async fn test_hello_unary() -> Result<(), anyhow::Error> {
1919
let mut mocks = MockSet::new();
2020
mocks.insert(
21-
MockPath::new(Method::POST, "/example.Hello/HelloUnary"),
21+
MockPath::post("/example.Hello/HelloUnary"),
2222
Mock::new(
2323
MockRequest::pb(HelloRequest { name: "Dan".into() }),
2424
MockResponse::pb(HelloResponse {
2525
message: "Hello Dan!".into(),
2626
}),
2727
),
2828
);
29+
mocks.insert(
30+
MockPath::post("/example.Hello/HelloUnary"),
31+
Mock::new(
32+
MockRequest::pb(HelloRequest {
33+
name: "InternalError".into(),
34+
}),
35+
MockResponse::empty()
36+
.with_code(StatusCode::INTERNAL_SERVER_ERROR)
37+
.with_message("woops"),
38+
),
39+
);
40+
// mocks.insert(
41+
// MockPath::post("/example.Hello/HelloUnary"),
42+
// Mock::new(
43+
// MockRequest::pb(HelloRequest {
44+
// name: "Header".into(),
45+
// })
46+
// .with_headers(HeaderMap::from_iter([(
47+
// HeaderName::from_static("some-header"),
48+
// HeaderValue::from_static(":D"),
49+
// )])),
50+
// MockResponse::pb(HelloResponse {
51+
// message: "Hello Header!".into(),
52+
// }),
53+
// ),
54+
// );
2955

3056
let server = GrpcMockServer::new("example.Hello", mocks)?;
3157
server.start().await?;
@@ -36,28 +62,52 @@ mod tests {
3662
.await?;
3763
let mut client = HelloClient::new(channel);
3864

65+
// Success response
3966
let result = client
40-
.hello_unary(HelloRequest { name: "Dan".into() })
67+
.hello_unary(HelloRequest {
68+
name: "Header".into(),
69+
})
4170
.await;
4271
dbg!(&result);
43-
assert!(result.is_ok());
44-
72+
//assert!(result.is_ok());
73+
74+
// Success response w/ header matching
75+
// let mut request = tonic::Request::new(HelloRequest { name: "Dan".into() });
76+
// request
77+
// .metadata_mut()
78+
// .insert("some-header", ":D".parse().unwrap());
79+
// let result = client.hello_unary(request).await;
80+
// dbg!(&result);
81+
// assert!(result.is_ok());
82+
83+
// Error response (mock not found)
4584
let result = client
4685
.hello_unary(HelloRequest {
47-
name: "NotFound1".into(),
86+
name: "NotFoundError".into(),
4887
})
4988
.await;
5089
dbg!(&result);
5190
assert!(result.is_err_and(|e| e.code() == tonic::Code::NotFound));
5291

92+
// Error response (internal)
93+
let result = client
94+
.hello_unary(HelloRequest {
95+
name: "InternalError".into(),
96+
})
97+
.await;
98+
dbg!(&result);
99+
assert!(
100+
result.is_err_and(|e| { e.code() == tonic::Code::Internal && e.message() == "woops" })
101+
);
102+
53103
Ok(())
54104
}
55105

56106
#[test_log::test(tokio::test)]
57107
async fn test_hello_streaming() -> Result<(), anyhow::Error> {
58108
let mut mocks = MockSet::new();
59109
mocks.insert(
60-
MockPath::new(Method::POST, "/example.Hello/HelloClientStreaming"),
110+
MockPath::post("/example.Hello/HelloClientStreaming"),
61111
Mock::new(
62112
MockRequest::stream([
63113
HelloRequest { name: "Dan".into() }.to_bytes(),
@@ -72,7 +122,7 @@ mod tests {
72122
),
73123
);
74124
mocks.insert(
75-
MockPath::new(Method::POST, "/example.Hello/HelloServerStreaming"),
125+
MockPath::post("/example.Hello/HelloServerStreaming"),
76126
Mock::new(
77127
MockRequest::pb(HelloRequest {
78128
name: "Dan, Gaurav".into(),
@@ -89,7 +139,7 @@ mod tests {
89139
),
90140
);
91141
mocks.insert(
92-
MockPath::new(Method::POST, "/example.Hello/HelloBidiStreaming"),
142+
MockPath::post("/example.Hello/HelloBidiStreaming"),
93143
Mock::new(
94144
MockRequest::pb_stream([
95145
HelloRequest {

mocktail-test/src/http_hello.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ mod tests {
2020
async fn test_hello_simple() -> Result<(), Error> {
2121
let mut mocks = MockSet::new();
2222
mocks.insert(
23-
MockPath::new(Method::POST, "/hello"),
23+
MockPath::post("/hello"),
2424
Mock::new(
2525
MockRequest::json(HelloRequest { name: "Dan".into() }),
2626
MockResponse::json(HelloResponse {

mocktail-test/src/http_simple.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ mod tests {
88
async fn test_simple_server_streaming() -> Result<(), Error> {
99
let mut mocks = MockSet::new();
1010
mocks.insert(
11-
MockPath::new(Method::POST, "/server-stream"),
11+
MockPath::post("/server-stream"),
1212
Mock::new(
1313
MockRequest::empty(),
1414
MockResponse::stream(["msg1", "msg2", "msg3"]),

mocktail-test/src/http_sse.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ mod tests {
99
async fn test_sse_streaming() -> Result<(), Error> {
1010
let mut mocks = MockSet::new();
1111
mocks.insert(
12-
MockPath::new(Method::POST, "/sse-stream"),
12+
MockPath::post("/sse-stream"),
1313
Mock::new(
1414
MockRequest::empty(),
1515
MockResponse::stream([

mocktail/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mocktail"
3-
version = "0.1.1-alpha"
3+
version = "0.1.2-alpha"
44
edition = "2021"
55
authors = ["Dan Clark", "Gaurav Kumbhat"]
66
description = "HTTP & gRPC server mocking for Rust"

mocktail/src/mock.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
mod body;
22
pub use body::{HyperBoxBody, MockBody, TonicBoxBody};
33

4-
mod path;
5-
pub use path::MockPath;
6-
74
mod set;
8-
pub use set::MockSet;
5+
pub use set::{MockPath, MockSet};
96

107
mod request;
118
pub use request::MockRequest;

mocktail/src/mock/body.rs

+24-27
Original file line numberDiff line numberDiff line change
@@ -16,45 +16,42 @@ pub enum MockBody {
1616
}
1717

1818
impl MockBody {
19+
pub fn is_empty(&self) -> bool {
20+
self.len() == 0
21+
}
22+
23+
pub fn len(&self) -> usize {
24+
match self {
25+
MockBody::Empty => 0,
26+
MockBody::Full(chunk) => chunk.len(),
27+
MockBody::Stream(chunks) => chunks.iter().map(|chunk| chunk.len()).sum(),
28+
}
29+
}
30+
31+
pub fn chunks(&self) -> Vec<Bytes> {
32+
match self {
33+
MockBody::Empty => vec![],
34+
MockBody::Full(chunk) => vec![chunk.clone()],
35+
MockBody::Stream(chunks) => chunks.clone(),
36+
}
37+
}
38+
1939
/// Returns a type-erased HTTP body for hyper.
2040
pub fn to_hyper_boxed(&self) -> HyperBoxBody {
2141
match self {
2242
MockBody::Empty => Empty::new().map_err(|err| match err {}).boxed(),
23-
MockBody::Full(data) => Full::new(data.clone())
43+
MockBody::Full(chunk) => Full::new(chunk.clone())
2444
.map_err(|never| match never {})
2545
.boxed(),
26-
MockBody::Stream(data) => {
27-
let messages: Vec<Result<_, hyper::Error>> = data
46+
MockBody::Stream(chunks) => {
47+
let messages: Vec<Result<_, hyper::Error>> = chunks
2848
.iter()
29-
.map(|message| Ok(Frame::data(message.clone())))
49+
.map(|chunk| Ok(Frame::data(chunk.clone())))
3050
.collect();
3151
HyperBoxBody::new(StreamBody::new(stream::iter(messages)))
3252
}
3353
}
3454
}
35-
36-
/// Returns a type-erased HTTP body for tonic.
37-
pub fn to_tonic_boxed(&self) -> TonicBoxBody {
38-
match self {
39-
MockBody::Empty => tonic::body::empty_body(),
40-
MockBody::Full(data) => tonic::body::boxed(Full::new(data.clone())),
41-
MockBody::Stream(data) => {
42-
let messages: Vec<Result<_, tonic::Status>> = data
43-
.iter()
44-
.map(|message| Ok(Frame::data(message.clone())))
45-
.collect();
46-
TonicBoxBody::new(StreamBody::new(stream::iter(messages)))
47-
}
48-
}
49-
}
50-
51-
pub fn messages(&self) -> Vec<Bytes> {
52-
match self {
53-
MockBody::Empty => vec![],
54-
MockBody::Full(bytes) => vec![bytes.clone()],
55-
MockBody::Stream(items) => items.clone(),
56-
}
57-
}
5855
}
5956

6057
impl PartialEq<[u8]> for MockBody {

mocktail/src/mock/path.rs

-37
This file was deleted.

mocktail/src/mock/response.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ pub struct MockResponse {
1010
pub code: http::StatusCode,
1111
pub headers: HeaderMap,
1212
pub body: MockBody,
13-
pub error: Option<String>,
13+
pub message: Option<String>,
1414
}
1515

1616
impl MockResponse {
@@ -82,8 +82,8 @@ impl MockResponse {
8282
self
8383
}
8484

85-
pub fn with_error(mut self, error: String) -> Self {
86-
self.error = Some(error);
85+
pub fn with_message(mut self, message: impl Into<String>) -> Self {
86+
self.message = Some(message.into());
8787
self
8888
}
8989

@@ -99,7 +99,11 @@ impl MockResponse {
9999
&self.body
100100
}
101101

102-
pub fn error(&self) -> Option<&str> {
103-
self.error.as_deref()
102+
pub fn message(&self) -> Option<&str> {
103+
self.message.as_deref()
104+
}
105+
106+
pub fn is_error(&self) -> bool {
107+
!matches!(self.code(), http::StatusCode::OK)
104108
}
105109
}

0 commit comments

Comments
 (0)