actix_web_lab/
test_response_macros.rs

1/// Quickly write tests that check various parts of a `ServiceResponse`.
2///
3/// An async test must be used (e.g., `#[actix_web::test]`) if used to assert on response body.
4///
5/// # Examples
6/// ```
7/// use actix_web::{
8///     dev::ServiceResponse, http::header::ContentType, test::TestRequest, HttpResponse,
9/// };
10/// use actix_web_lab::assert_response_matches;
11///
12/// # actix_web::rt::System::new().block_on(async {
13/// let res = ServiceResponse::new(
14///     TestRequest::default().to_http_request(),
15///     HttpResponse::Created()
16///         .insert_header(("date", "today"))
17///         .insert_header(("set-cookie", "a=b"))
18///         .body("Hello World!"),
19/// );
20///
21/// assert_response_matches!(res, CREATED);
22/// assert_response_matches!(res, CREATED; "date" => "today");
23/// assert_response_matches!(res, CREATED; @raw "Hello World!");
24///
25/// let res = ServiceResponse::new(
26///     TestRequest::default().to_http_request(),
27///     HttpResponse::Created()
28///         .insert_header(("date", "today"))
29///         .insert_header(("set-cookie", "a=b"))
30///         .body("Hello World!"),
31/// );
32///
33/// assert_response_matches!(res, CREATED;
34///     "date" => "today"
35///     "set-cookie" => "a=b";
36///     @raw "Hello World!"
37/// );
38///
39/// let res = ServiceResponse::new(
40///     TestRequest::default().to_http_request(),
41///     HttpResponse::Created()
42///         .content_type(ContentType::json())
43///         .insert_header(("date", "today"))
44///         .insert_header(("set-cookie", "a=b"))
45///         .body(r#"{"abc":"123"}"#),
46/// );
47///
48/// assert_response_matches!(res, CREATED; @json { "abc": "123" });
49/// # });
50/// ```
51#[macro_export]
52macro_rules! assert_response_matches {
53    ($res:ident, $status:ident) => {{
54        assert_eq!($res.status(), ::actix_web::http::StatusCode::$status)
55    }};
56
57    ($res:ident, $status:ident; $($hdr_name:expr => $hdr_val:expr)+) => {{
58        assert_response_matches!($res, $status);
59
60        $(
61            assert_eq!(
62                $res.headers().get(::actix_web::http::header::HeaderName::from_static($hdr_name)).unwrap(),
63                &::actix_web::http::header::HeaderValue::from_static($hdr_val),
64            );
65        )+
66    }};
67
68    ($res:ident, $status:ident; @raw $payload:expr) => {{
69        assert_response_matches!($res, $status);
70        assert_eq!(::actix_web::test::read_body($res).await, $payload);
71    }};
72
73    ($res:ident, $status:ident; $($hdr_name:expr => $hdr_val:expr)+; @raw $payload:expr) => {{
74        assert_response_matches!($res, $status; $($hdr_name => $hdr_val)+);
75        assert_eq!(::actix_web::test::read_body($res).await, $payload);
76    }};
77
78    ($res:ident, $status:ident; @json $payload:tt) => {{
79        assert_response_matches!($res, $status);
80        assert_eq!(
81            ::actix_web::test::read_body_json::<$crate::__reexports::serde_json::Value, _>($res).await,
82            $crate::__reexports::serde_json::json!($payload),
83        );
84    }};
85}
86
87pub use assert_response_matches;
88
89#[cfg(test)]
90mod tests {
91    use actix_web::{
92        dev::ServiceResponse, http::header::ContentType, test::TestRequest, HttpResponse,
93    };
94
95    use super::*;
96
97    #[actix_web::test]
98    async fn response_matching() {
99        let res = ServiceResponse::new(
100            TestRequest::default().to_http_request(),
101            HttpResponse::Created()
102                .insert_header(("date", "today"))
103                .insert_header(("set-cookie", "a=b"))
104                .body("Hello World!"),
105        );
106
107        assert_response_matches!(res, CREATED);
108        assert_response_matches!(res, CREATED; "date" => "today");
109        assert_response_matches!(res, CREATED; @raw "Hello World!");
110
111        let res = ServiceResponse::new(
112            TestRequest::default().to_http_request(),
113            HttpResponse::Created()
114                .insert_header(("date", "today"))
115                .insert_header(("set-cookie", "a=b"))
116                .body("Hello World!"),
117        );
118        assert_response_matches!(res, CREATED;
119            "date" => "today"
120            "set-cookie" => "a=b";
121            @raw "Hello World!"
122        );
123
124        let res = ServiceResponse::new(
125            TestRequest::default().to_http_request(),
126            HttpResponse::Created()
127                .content_type(ContentType::json())
128                .insert_header(("date", "today"))
129                .insert_header(("set-cookie", "a=b"))
130                .body(r#"{"abc":"123"}"#),
131        );
132
133        assert_response_matches!(res, CREATED; @json { "abc": "123" });
134    }
135}