hyper_mock_client/
lib.rs

1//! # hyper-mock-client
2//!
3//! `hyper-mock-client` is a hyper::client mock to test tower::services such as axum::router
4//!
5//! ## Example
6//!
7//! ```
8//! mod tests {
9//!    use hyper::{Request,Body, StatusCode};
10//!    use axum::{Router};
11//!    use hyper_mock_client::MockClient;
12//!
13//!    let app = super::MakeApiApp(); 
14//!    let mut client = MockClient::new(app);
15//!
16//!    let resp = client.get("/status").await;
17//!
18//! ```
19
20use axum::Router;
21use axum::response::Response;
22use hyper::service::Service;
23use hyper::{Uri, Request, Body};
24
25
26/// The mock client, instantiate with `new`  
27pub struct MockClient {
28    svc: Router,
29}
30
31impl MockClient {
32    /// Creates a new mock client for the service
33    pub fn new(svc: Router) -> MockClient {
34        MockClient { svc }
35    }
36    
37    /// Simplified GET request
38    pub async fn get(&mut self, uri: Uri) -> Response {
39        let req = Request::builder().uri(uri.to_string()).body(Body::empty()).unwrap();
40        self.request(req).await
41    }
42
43    /// Full `hyper::Request` request
44    pub async fn request(&mut self, req: Request<Body>) -> Response {
45        self.svc.call(req).await.unwrap()
46    }
47}
48
49#[cfg(test)]
50mod tests {
51    use axum::{
52        Router,
53        routing::{get,post,put,delete}, 
54        http::StatusCode, body::Bytes,
55    };
56    use hyper::Body;
57
58    use super::*;
59
60    async fn ok_handler() -> Result<String, StatusCode> {
61        Ok("pong".to_string())
62    }
63    async fn created_handler() -> Result<String, StatusCode> {
64        Err(StatusCode::CREATED)
65    }
66    async fn echo_handler(body: Bytes) -> Result<Bytes, StatusCode> {
67        Ok(body)
68    }
69    async fn error_handler() -> Result<String, StatusCode> {
70        Err(StatusCode::NOT_ACCEPTABLE)
71    }
72    
73    #[tokio::test]
74    async fn test_basic() {
75        let app = Router::new()
76            .route("/ping", get(ok_handler))
77            .route("/ping", post(created_handler))
78            .route("/ping", put(echo_handler))
79            .route("/ping", delete(error_handler));
80
81        let mut client = MockClient::new(app);
82        
83        let path = Uri::from_static("/ping");
84        let resp = client.get(path).await;
85        assert_eq!( resp.status(), StatusCode::OK);
86        let b = hyper::body::to_bytes(resp).await.unwrap();
87        assert_eq!( b , "pong" );
88
89        let path = Uri::from_static("/ping");
90        let req = Request::post(path).body(Body::empty()).unwrap();
91        let resp = client.request(req).await;
92        assert_eq!( resp.status(), StatusCode::CREATED);
93
94        let path = Uri::from_static("/ping");
95        let bod = Body::from("ola");
96        let req = Request::put(path).body(bod).unwrap();
97        let resp = client.request(req).await;
98        assert_eq!( resp.status(), StatusCode::OK);
99        assert_eq!( hyper::body::to_bytes(resp).await.unwrap(), Bytes::from("ola"));
100
101        let path = Uri::from_static("/ping");
102        let req = Request::delete(path).body(Body::empty()).unwrap();
103        let resp = client.request(req).await;
104        assert_eq!( resp.status(), StatusCode::NOT_ACCEPTABLE);
105
106    }
107}