1 //! Various helpers for Actix applications to use during testing.
2 
3 use std::{net::SocketAddr, rc::Rc};
4 
5 pub use actix_http::test::TestBuffer;
6 use actix_http::{
7     body,
8     http::{header::IntoHeaderPair, Method, StatusCode, Uri, Version},
9     test::TestRequest as HttpTestRequest,
10     Extensions, Request,
11 };
12 use actix_router::{Path, ResourceDef, Url};
13 use actix_service::{IntoService, IntoServiceFactory, Service, ServiceFactory};
14 use actix_utils::future::{ok, poll_fn};
15 use futures_core::Stream;
16 use futures_util::StreamExt as _;
17 use serde::{de::DeserializeOwned, Serialize};
18 
19 #[cfg(feature = "cookies")]
20 use crate::cookie::{Cookie, CookieJar};
21 use crate::{
22     app_service::AppInitServiceState,
23     config::AppConfig,
24     data::Data,
25     dev::{Body, MessageBody, Payload},
26     http::header::ContentType,
27     rmap::ResourceMap,
28     service::{ServiceRequest, ServiceResponse},
29     web::{Bytes, BytesMut},
30     Error, HttpRequest, HttpResponse, HttpResponseBuilder,
31 };
32 
33 /// Create service that always responds with `HttpResponse::Ok()` and no body.
ok_service( ) -> impl Service<ServiceRequest, Response = ServiceResponse<Body>, Error = Error>34 pub fn ok_service(
35 ) -> impl Service<ServiceRequest, Response = ServiceResponse<Body>, Error = Error> {
36     default_service(StatusCode::OK)
37 }
38 
39 /// Create service that always responds with given status code and no body.
default_service( status_code: StatusCode, ) -> impl Service<ServiceRequest, Response = ServiceResponse<Body>, Error = Error>40 pub fn default_service(
41     status_code: StatusCode,
42 ) -> impl Service<ServiceRequest, Response = ServiceResponse<Body>, Error = Error> {
43     (move |req: ServiceRequest| {
44         ok(req.into_response(HttpResponseBuilder::new(status_code).finish()))
45     })
46     .into_service()
47 }
48 
49 /// Initialize service from application builder instance.
50 ///
51 /// ```
52 /// use actix_service::Service;
53 /// use actix_web::{test, web, App, HttpResponse, http::StatusCode};
54 ///
55 /// #[actix_rt::test]
56 /// async fn test_init_service() {
57 ///     let app = test::init_service(
58 ///         App::new()
59 ///             .service(web::resource("/test").to(|| async { HttpResponse::Ok() }))
60 ///     ).await;
61 ///
62 ///     // Create request object
63 ///     let req = test::TestRequest::with_uri("/test").to_request();
64 ///
65 ///     // Execute application
66 ///     let resp = app.call(req).await.unwrap();
67 ///     assert_eq!(resp.status(), StatusCode::OK);
68 /// }
69 /// ```
init_service<R, S, B, E>( app: R, ) -> impl Service<Request, Response = ServiceResponse<B>, Error = E> where R: IntoServiceFactory<S, Request>, S: ServiceFactory<Request, Config = AppConfig, Response = ServiceResponse<B>, Error = E>, S::InitError: std::fmt::Debug,70 pub async fn init_service<R, S, B, E>(
71     app: R,
72 ) -> impl Service<Request, Response = ServiceResponse<B>, Error = E>
73 where
74     R: IntoServiceFactory<S, Request>,
75     S: ServiceFactory<Request, Config = AppConfig, Response = ServiceResponse<B>, Error = E>,
76     S::InitError: std::fmt::Debug,
77 {
78     try_init_service(app)
79         .await
80         .expect("service initialization failed")
81 }
82 
83 /// Fallible version of [`init_service`] that allows testing initialization errors.
try_init_service<R, S, B, E>( app: R, ) -> Result<impl Service<Request, Response = ServiceResponse<B>, Error = E>, S::InitError> where R: IntoServiceFactory<S, Request>, S: ServiceFactory<Request, Config = AppConfig, Response = ServiceResponse<B>, Error = E>, S::InitError: std::fmt::Debug,84 pub(crate) async fn try_init_service<R, S, B, E>(
85     app: R,
86 ) -> Result<impl Service<Request, Response = ServiceResponse<B>, Error = E>, S::InitError>
87 where
88     R: IntoServiceFactory<S, Request>,
89     S: ServiceFactory<Request, Config = AppConfig, Response = ServiceResponse<B>, Error = E>,
90     S::InitError: std::fmt::Debug,
91 {
92     let srv = app.into_factory();
93     srv.new_service(AppConfig::default()).await
94 }
95 
96 /// Calls service and waits for response future completion.
97 ///
98 /// ```
99 /// use actix_web::{test, web, App, HttpResponse, http::StatusCode};
100 ///
101 /// #[actix_rt::test]
102 /// async fn test_response() {
103 ///     let app = test::init_service(
104 ///         App::new()
105 ///             .service(web::resource("/test").to(|| async {
106 ///                 HttpResponse::Ok()
107 ///             }))
108 ///     ).await;
109 ///
110 ///     // Create request object
111 ///     let req = test::TestRequest::with_uri("/test").to_request();
112 ///
113 ///     // Call application
114 ///     let resp = test::call_service(&app, req).await;
115 ///     assert_eq!(resp.status(), StatusCode::OK);
116 /// }
117 /// ```
call_service<S, R, B, E>(app: &S, req: R) -> S::Response where S: Service<R, Response = ServiceResponse<B>, Error = E>, E: std::fmt::Debug,118 pub async fn call_service<S, R, B, E>(app: &S, req: R) -> S::Response
119 where
120     S: Service<R, Response = ServiceResponse<B>, Error = E>,
121     E: std::fmt::Debug,
122 {
123     app.call(req).await.unwrap()
124 }
125 
126 /// Helper function that returns a response body of a TestRequest
127 ///
128 /// ```
129 /// use actix_web::{test, web, App, HttpResponse, http::header};
130 /// use bytes::Bytes;
131 ///
132 /// #[actix_rt::test]
133 /// async fn test_index() {
134 ///     let app = test::init_service(
135 ///         App::new().service(
136 ///             web::resource("/index.html")
137 ///                 .route(web::post().to(|| async {
138 ///                     HttpResponse::Ok().body("welcome!")
139 ///                 })))
140 ///     ).await;
141 ///
142 ///     let req = test::TestRequest::post()
143 ///         .uri("/index.html")
144 ///         .header(header::CONTENT_TYPE, "application/json")
145 ///         .to_request();
146 ///
147 ///     let result = test::read_response(&app, req).await;
148 ///     assert_eq!(result, Bytes::from_static(b"welcome!"));
149 /// }
150 /// ```
read_response<S, B>(app: &S, req: Request) -> Bytes where S: Service<Request, Response = ServiceResponse<B>, Error = Error>, B: MessageBody + Unpin, B::Error: Into<Error>,151 pub async fn read_response<S, B>(app: &S, req: Request) -> Bytes
152 where
153     S: Service<Request, Response = ServiceResponse<B>, Error = Error>,
154     B: MessageBody + Unpin,
155     B::Error: Into<Error>,
156 {
157     let resp = app
158         .call(req)
159         .await
160         .unwrap_or_else(|e| panic!("read_response failed at application call: {}", e));
161 
162     let body = resp.into_body();
163     let mut bytes = BytesMut::new();
164 
165     actix_rt::pin!(body);
166     while let Some(item) = poll_fn(|cx| body.as_mut().poll_next(cx)).await {
167         bytes.extend_from_slice(&item.map_err(Into::into).unwrap());
168     }
169 
170     bytes.freeze()
171 }
172 
173 /// Helper function that returns a response body of a ServiceResponse.
174 ///
175 /// ```
176 /// use actix_web::{test, web, App, HttpResponse, http::header};
177 /// use bytes::Bytes;
178 ///
179 /// #[actix_rt::test]
180 /// async fn test_index() {
181 ///     let app = test::init_service(
182 ///         App::new().service(
183 ///             web::resource("/index.html")
184 ///                 .route(web::post().to(|| async {
185 ///                     HttpResponse::Ok().body("welcome!")
186 ///                 })))
187 ///     ).await;
188 ///
189 ///     let req = test::TestRequest::post()
190 ///         .uri("/index.html")
191 ///         .header(header::CONTENT_TYPE, "application/json")
192 ///         .to_request();
193 ///
194 ///     let resp = test::call_service(&app, req).await;
195 ///     let result = test::read_body(resp).await;
196 ///     assert_eq!(result, Bytes::from_static(b"welcome!"));
197 /// }
198 /// ```
read_body<B>(res: ServiceResponse<B>) -> Bytes where B: MessageBody + Unpin, B::Error: Into<Error>,199 pub async fn read_body<B>(res: ServiceResponse<B>) -> Bytes
200 where
201     B: MessageBody + Unpin,
202     B::Error: Into<Error>,
203 {
204     let body = res.into_body();
205     let mut bytes = BytesMut::new();
206 
207     actix_rt::pin!(body);
208     while let Some(item) = poll_fn(|cx| body.as_mut().poll_next(cx)).await {
209         bytes.extend_from_slice(&item.map_err(Into::into).unwrap());
210     }
211 
212     bytes.freeze()
213 }
214 
215 /// Helper function that returns a deserialized response body of a ServiceResponse.
216 ///
217 /// ```
218 /// use actix_web::{App, test, web, HttpResponse, http::header};
219 /// use serde::{Serialize, Deserialize};
220 ///
221 /// #[derive(Serialize, Deserialize)]
222 /// pub struct Person {
223 ///     id: String,
224 ///     name: String,
225 /// }
226 ///
227 /// #[actix_rt::test]
228 /// async fn test_post_person() {
229 ///     let app = test::init_service(
230 ///         App::new().service(
231 ///             web::resource("/people")
232 ///                 .route(web::post().to(|person: web::Json<Person>| async {
233 ///                     HttpResponse::Ok()
234 ///                         .json(person)})
235 ///                     ))
236 ///     ).await;
237 ///
238 ///     let payload = r#"{"id":"12345","name":"User name"}"#.as_bytes();
239 ///
240 ///     let resp = test::TestRequest::post()
241 ///         .uri("/people")
242 ///         .header(header::CONTENT_TYPE, "application/json")
243 ///         .set_payload(payload)
244 ///         .send_request(&mut app)
245 ///         .await;
246 ///
247 ///     assert!(resp.status().is_success());
248 ///
249 ///     let result: Person = test::read_body_json(resp).await;
250 /// }
251 /// ```
read_body_json<T, B>(res: ServiceResponse<B>) -> T where B: MessageBody + Unpin, B::Error: Into<Error>, T: DeserializeOwned,252 pub async fn read_body_json<T, B>(res: ServiceResponse<B>) -> T
253 where
254     B: MessageBody + Unpin,
255     B::Error: Into<Error>,
256     T: DeserializeOwned,
257 {
258     let body = read_body(res).await;
259 
260     serde_json::from_slice(&body).unwrap_or_else(|e| {
261         panic!(
262             "read_response_json failed during deserialization of body: {:?}, {}",
263             body, e
264         )
265     })
266 }
267 
load_stream<S>(mut stream: S) -> Result<Bytes, Error> where S: Stream<Item = Result<Bytes, Error>> + Unpin,268 pub async fn load_stream<S>(mut stream: S) -> Result<Bytes, Error>
269 where
270     S: Stream<Item = Result<Bytes, Error>> + Unpin,
271 {
272     let mut data = BytesMut::new();
273     while let Some(item) = stream.next().await {
274         data.extend_from_slice(&item?);
275     }
276     Ok(data.freeze())
277 }
278 
load_body<B>(body: B) -> Result<Bytes, Error> where B: MessageBody + Unpin, B::Error: Into<Error>,279 pub async fn load_body<B>(body: B) -> Result<Bytes, Error>
280 where
281     B: MessageBody + Unpin,
282     B::Error: Into<Error>,
283 {
284     body::to_bytes(body).await.map_err(Into::into)
285 }
286 
287 /// Helper function that returns a deserialized response body of a TestRequest
288 ///
289 /// ```
290 /// use actix_web::{App, test, web, HttpResponse, http::header};
291 /// use serde::{Serialize, Deserialize};
292 ///
293 /// #[derive(Serialize, Deserialize)]
294 /// pub struct Person {
295 ///     id: String,
296 ///     name: String
297 /// }
298 ///
299 /// #[actix_rt::test]
300 /// async fn test_add_person() {
301 ///     let app = test::init_service(
302 ///         App::new().service(
303 ///             web::resource("/people")
304 ///                 .route(web::post().to(|person: web::Json<Person>| async {
305 ///                     HttpResponse::Ok()
306 ///                         .json(person)})
307 ///                     ))
308 ///     ).await;
309 ///
310 ///     let payload = r#"{"id":"12345","name":"User name"}"#.as_bytes();
311 ///
312 ///     let req = test::TestRequest::post()
313 ///         .uri("/people")
314 ///         .header(header::CONTENT_TYPE, "application/json")
315 ///         .set_payload(payload)
316 ///         .to_request();
317 ///
318 ///     let result: Person = test::read_response_json(&mut app, req).await;
319 /// }
320 /// ```
read_response_json<S, B, T>(app: &S, req: Request) -> T where S: Service<Request, Response = ServiceResponse<B>, Error = Error>, B: MessageBody + Unpin, B::Error: Into<Error>, T: DeserializeOwned,321 pub async fn read_response_json<S, B, T>(app: &S, req: Request) -> T
322 where
323     S: Service<Request, Response = ServiceResponse<B>, Error = Error>,
324     B: MessageBody + Unpin,
325     B::Error: Into<Error>,
326     T: DeserializeOwned,
327 {
328     let body = read_response(app, req).await;
329 
330     serde_json::from_slice(&body).unwrap_or_else(|_| {
331         panic!(
332             "read_response_json failed during deserialization of body: {:?}",
333             body
334         )
335     })
336 }
337 
338 /// Test `Request` builder.
339 ///
340 /// For unit testing, actix provides a request builder type and a simple handler runner. TestRequest implements a builder-like pattern.
341 /// You can generate various types of request via TestRequest's methods:
342 ///  * `TestRequest::to_request` creates `actix_http::Request` instance.
343 ///  * `TestRequest::to_srv_request` creates `ServiceRequest` instance, which is used for testing middlewares and chain adapters.
344 ///  * `TestRequest::to_srv_response` creates `ServiceResponse` instance.
345 ///  * `TestRequest::to_http_request` creates `HttpRequest` instance, which is used for testing handlers.
346 ///
347 /// ```
348 /// use actix_web::{test, HttpRequest, HttpResponse, HttpMessage};
349 /// use actix_web::http::{header, StatusCode};
350 ///
351 /// async fn index(req: HttpRequest) -> HttpResponse {
352 ///     if let Some(hdr) = req.headers().get(header::CONTENT_TYPE) {
353 ///         HttpResponse::Ok().into()
354 ///     } else {
355 ///         HttpResponse::BadRequest().into()
356 ///     }
357 /// }
358 ///
359 /// #[test]
360 /// fn test_index() {
361 ///     let req = test::TestRequest::default().insert_header("content-type", "text/plain")
362 ///         .to_http_request();
363 ///
364 ///     let resp = index(req).await.unwrap();
365 ///     assert_eq!(resp.status(), StatusCode::OK);
366 ///
367 ///     let req = test::TestRequest::default().to_http_request();
368 ///     let resp = index(req).await.unwrap();
369 ///     assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
370 /// }
371 /// ```
372 pub struct TestRequest {
373     req: HttpTestRequest,
374     rmap: ResourceMap,
375     config: AppConfig,
376     path: Path<Url>,
377     peer_addr: Option<SocketAddr>,
378     app_data: Extensions,
379     #[cfg(feature = "cookies")]
380     cookies: CookieJar,
381 }
382 
383 impl Default for TestRequest {
default() -> TestRequest384     fn default() -> TestRequest {
385         TestRequest {
386             req: HttpTestRequest::default(),
387             rmap: ResourceMap::new(ResourceDef::new("")),
388             config: AppConfig::default(),
389             path: Path::new(Url::new(Uri::default())),
390             peer_addr: None,
391             app_data: Extensions::new(),
392             #[cfg(feature = "cookies")]
393             cookies: CookieJar::new(),
394         }
395     }
396 }
397 
398 #[allow(clippy::wrong_self_convention)]
399 impl TestRequest {
400     /// Create TestRequest and set request uri
with_uri(path: &str) -> TestRequest401     pub fn with_uri(path: &str) -> TestRequest {
402         TestRequest::default().uri(path)
403     }
404 
405     /// Create TestRequest and set method to `Method::GET`
get() -> TestRequest406     pub fn get() -> TestRequest {
407         TestRequest::default().method(Method::GET)
408     }
409 
410     /// Create TestRequest and set method to `Method::POST`
post() -> TestRequest411     pub fn post() -> TestRequest {
412         TestRequest::default().method(Method::POST)
413     }
414 
415     /// Create TestRequest and set method to `Method::PUT`
put() -> TestRequest416     pub fn put() -> TestRequest {
417         TestRequest::default().method(Method::PUT)
418     }
419 
420     /// Create TestRequest and set method to `Method::PATCH`
patch() -> TestRequest421     pub fn patch() -> TestRequest {
422         TestRequest::default().method(Method::PATCH)
423     }
424 
425     /// Create TestRequest and set method to `Method::DELETE`
delete() -> TestRequest426     pub fn delete() -> TestRequest {
427         TestRequest::default().method(Method::DELETE)
428     }
429 
430     /// Set HTTP version of this request
version(mut self, ver: Version) -> Self431     pub fn version(mut self, ver: Version) -> Self {
432         self.req.version(ver);
433         self
434     }
435 
436     /// Set HTTP method of this request
method(mut self, meth: Method) -> Self437     pub fn method(mut self, meth: Method) -> Self {
438         self.req.method(meth);
439         self
440     }
441 
442     /// Set HTTP Uri of this request
uri(mut self, path: &str) -> Self443     pub fn uri(mut self, path: &str) -> Self {
444         self.req.uri(path);
445         self
446     }
447 
448     /// Insert a header, replacing any that were set with an equivalent field name.
insert_header<H>(mut self, header: H) -> Self where H: IntoHeaderPair,449     pub fn insert_header<H>(mut self, header: H) -> Self
450     where
451         H: IntoHeaderPair,
452     {
453         self.req.insert_header(header);
454         self
455     }
456 
457     /// Append a header, keeping any that were set with an equivalent field name.
append_header<H>(mut self, header: H) -> Self where H: IntoHeaderPair,458     pub fn append_header<H>(mut self, header: H) -> Self
459     where
460         H: IntoHeaderPair,
461     {
462         self.req.append_header(header);
463         self
464     }
465 
466     /// Set cookie for this request.
467     #[cfg(feature = "cookies")]
cookie(mut self, cookie: Cookie<'_>) -> Self468     pub fn cookie(mut self, cookie: Cookie<'_>) -> Self {
469         self.cookies.add(cookie.into_owned());
470         self
471     }
472 
473     /// Set request path pattern parameter
param(mut self, name: &'static str, value: &'static str) -> Self474     pub fn param(mut self, name: &'static str, value: &'static str) -> Self {
475         self.path.add_static(name, value);
476         self
477     }
478 
479     /// Set peer addr
peer_addr(mut self, addr: SocketAddr) -> Self480     pub fn peer_addr(mut self, addr: SocketAddr) -> Self {
481         self.peer_addr = Some(addr);
482         self
483     }
484 
485     /// Set request payload
set_payload<B: Into<Bytes>>(mut self, data: B) -> Self486     pub fn set_payload<B: Into<Bytes>>(mut self, data: B) -> Self {
487         self.req.set_payload(data);
488         self
489     }
490 
491     /// Serialize `data` to a URL encoded form and set it as the request payload. The `Content-Type`
492     /// header is set to `application/x-www-form-urlencoded`.
set_form<T: Serialize>(mut self, data: &T) -> Self493     pub fn set_form<T: Serialize>(mut self, data: &T) -> Self {
494         let bytes = serde_urlencoded::to_string(data)
495             .expect("Failed to serialize test data as a urlencoded form");
496         self.req.set_payload(bytes);
497         self.req.insert_header(ContentType::form_url_encoded());
498         self
499     }
500 
501     /// Serialize `data` to JSON and set it as the request payload. The `Content-Type` header is
502     /// set to `application/json`.
set_json<T: Serialize>(mut self, data: &T) -> Self503     pub fn set_json<T: Serialize>(mut self, data: &T) -> Self {
504         let bytes = serde_json::to_string(data).expect("Failed to serialize test data to json");
505         self.req.set_payload(bytes);
506         self.req.insert_header(ContentType::json());
507         self
508     }
509 
510     /// Set application data. This is equivalent of `App::data()` method
511     /// for testing purpose.
data<T: 'static>(mut self, data: T) -> Self512     pub fn data<T: 'static>(mut self, data: T) -> Self {
513         self.app_data.insert(Data::new(data));
514         self
515     }
516 
517     /// Set application data. This is equivalent of `App::app_data()` method
518     /// for testing purpose.
app_data<T: 'static>(mut self, data: T) -> Self519     pub fn app_data<T: 'static>(mut self, data: T) -> Self {
520         self.app_data.insert(data);
521         self
522     }
523 
524     #[cfg(test)]
525     /// Set request config
rmap(mut self, rmap: ResourceMap) -> Self526     pub(crate) fn rmap(mut self, rmap: ResourceMap) -> Self {
527         self.rmap = rmap;
528         self
529     }
530 
finish(&mut self) -> Request531     fn finish(&mut self) -> Request {
532         // mut used when cookie feature is enabled
533         #[allow(unused_mut)]
534         let mut req = self.req.finish();
535 
536         #[cfg(feature = "cookies")]
537         {
538             use actix_http::http::header::{HeaderValue, COOKIE};
539 
540             let cookie: String = self
541                 .cookies
542                 .delta()
543                 // ensure only name=value is written to cookie header
544                 .map(|c| c.stripped().encoded().to_string())
545                 .collect::<Vec<_>>()
546                 .join("; ");
547 
548             if !cookie.is_empty() {
549                 req.headers_mut()
550                     .insert(COOKIE, HeaderValue::from_str(&cookie).unwrap());
551             }
552         }
553 
554         req
555     }
556 
557     /// Complete request creation and generate `Request` instance
to_request(mut self) -> Request558     pub fn to_request(mut self) -> Request {
559         let mut req = self.finish();
560         req.head_mut().peer_addr = self.peer_addr;
561         req
562     }
563 
564     /// Complete request creation and generate `ServiceRequest` instance
to_srv_request(mut self) -> ServiceRequest565     pub fn to_srv_request(mut self) -> ServiceRequest {
566         let (mut head, payload) = self.finish().into_parts();
567         head.peer_addr = self.peer_addr;
568         self.path.get_mut().update(&head.uri);
569 
570         let app_state = AppInitServiceState::new(Rc::new(self.rmap), self.config.clone());
571 
572         ServiceRequest::new(
573             HttpRequest::new(self.path, head, app_state, Rc::new(self.app_data)),
574             payload,
575         )
576     }
577 
578     /// Complete request creation and generate `ServiceResponse` instance
to_srv_response<B>(self, res: HttpResponse<B>) -> ServiceResponse<B>579     pub fn to_srv_response<B>(self, res: HttpResponse<B>) -> ServiceResponse<B> {
580         self.to_srv_request().into_response(res)
581     }
582 
583     /// Complete request creation and generate `HttpRequest` instance
to_http_request(mut self) -> HttpRequest584     pub fn to_http_request(mut self) -> HttpRequest {
585         let (mut head, _) = self.finish().into_parts();
586         head.peer_addr = self.peer_addr;
587         self.path.get_mut().update(&head.uri);
588 
589         let app_state = AppInitServiceState::new(Rc::new(self.rmap), self.config.clone());
590 
591         HttpRequest::new(self.path, head, app_state, Rc::new(self.app_data))
592     }
593 
594     /// Complete request creation and generate `HttpRequest` and `Payload` instances
to_http_parts(mut self) -> (HttpRequest, Payload)595     pub fn to_http_parts(mut self) -> (HttpRequest, Payload) {
596         let (mut head, payload) = self.finish().into_parts();
597         head.peer_addr = self.peer_addr;
598         self.path.get_mut().update(&head.uri);
599 
600         let app_state = AppInitServiceState::new(Rc::new(self.rmap), self.config.clone());
601 
602         let req = HttpRequest::new(self.path, head, app_state, Rc::new(self.app_data));
603 
604         (req, payload)
605     }
606 
607     /// Complete request creation, calls service and waits for response future completion.
send_request<S, B, E>(self, app: &S) -> S::Response where S: Service<Request, Response = ServiceResponse<B>, Error = E>, E: std::fmt::Debug,608     pub async fn send_request<S, B, E>(self, app: &S) -> S::Response
609     where
610         S: Service<Request, Response = ServiceResponse<B>, Error = E>,
611         E: std::fmt::Debug,
612     {
613         let req = self.to_request();
614         call_service(app, req).await
615     }
616 
617     #[cfg(test)]
set_server_hostname(&mut self, host: &str)618     pub fn set_server_hostname(&mut self, host: &str) {
619         self.config.set_host(host)
620     }
621 }
622 
623 #[cfg(test)]
624 mod tests {
625     use std::time::SystemTime;
626 
627     use actix_http::HttpMessage;
628     use serde::{Deserialize, Serialize};
629 
630     use super::*;
631     use crate::{http::header, web, App, HttpResponse, Responder};
632 
633     #[actix_rt::test]
test_basics()634     async fn test_basics() {
635         let req = TestRequest::default()
636             .version(Version::HTTP_2)
637             .insert_header(header::ContentType::json())
638             .insert_header(header::Date(SystemTime::now().into()))
639             .param("test", "123")
640             .data(10u32)
641             .app_data(20u64)
642             .peer_addr("127.0.0.1:8081".parse().unwrap())
643             .to_http_request();
644         assert!(req.headers().contains_key(header::CONTENT_TYPE));
645         assert!(req.headers().contains_key(header::DATE));
646         assert_eq!(
647             req.head().peer_addr,
648             Some("127.0.0.1:8081".parse().unwrap())
649         );
650         assert_eq!(&req.match_info()["test"], "123");
651         assert_eq!(req.version(), Version::HTTP_2);
652         let data = req.app_data::<Data<u32>>().unwrap();
653         assert!(req.app_data::<Data<u64>>().is_none());
654         assert_eq!(*data.get_ref(), 10);
655 
656         assert!(req.app_data::<u32>().is_none());
657         let data = req.app_data::<u64>().unwrap();
658         assert_eq!(*data, 20);
659     }
660 
661     #[actix_rt::test]
test_request_methods()662     async fn test_request_methods() {
663         let app = init_service(
664             App::new().service(
665                 web::resource("/index.html")
666                     .route(web::put().to(|| HttpResponse::Ok().body("put!")))
667                     .route(web::patch().to(|| HttpResponse::Ok().body("patch!")))
668                     .route(web::delete().to(|| HttpResponse::Ok().body("delete!"))),
669             ),
670         )
671         .await;
672 
673         let put_req = TestRequest::put()
674             .uri("/index.html")
675             .insert_header((header::CONTENT_TYPE, "application/json"))
676             .to_request();
677 
678         let result = read_response(&app, put_req).await;
679         assert_eq!(result, Bytes::from_static(b"put!"));
680 
681         let patch_req = TestRequest::patch()
682             .uri("/index.html")
683             .insert_header((header::CONTENT_TYPE, "application/json"))
684             .to_request();
685 
686         let result = read_response(&app, patch_req).await;
687         assert_eq!(result, Bytes::from_static(b"patch!"));
688 
689         let delete_req = TestRequest::delete().uri("/index.html").to_request();
690         let result = read_response(&app, delete_req).await;
691         assert_eq!(result, Bytes::from_static(b"delete!"));
692     }
693 
694     #[actix_rt::test]
test_response()695     async fn test_response() {
696         let app = init_service(
697             App::new().service(
698                 web::resource("/index.html")
699                     .route(web::post().to(|| HttpResponse::Ok().body("welcome!"))),
700             ),
701         )
702         .await;
703 
704         let req = TestRequest::post()
705             .uri("/index.html")
706             .insert_header((header::CONTENT_TYPE, "application/json"))
707             .to_request();
708 
709         let result = read_response(&app, req).await;
710         assert_eq!(result, Bytes::from_static(b"welcome!"));
711     }
712 
713     #[actix_rt::test]
test_send_request()714     async fn test_send_request() {
715         let app = init_service(
716             App::new().service(
717                 web::resource("/index.html")
718                     .route(web::get().to(|| HttpResponse::Ok().body("welcome!"))),
719             ),
720         )
721         .await;
722 
723         let resp = TestRequest::get()
724             .uri("/index.html")
725             .send_request(&app)
726             .await;
727 
728         let result = read_body(resp).await;
729         assert_eq!(result, Bytes::from_static(b"welcome!"));
730     }
731 
732     #[derive(Serialize, Deserialize)]
733     pub struct Person {
734         id: String,
735         name: String,
736     }
737 
738     #[actix_rt::test]
test_response_json()739     async fn test_response_json() {
740         let app = init_service(App::new().service(web::resource("/people").route(
741             web::post().to(|person: web::Json<Person>| HttpResponse::Ok().json(person)),
742         )))
743         .await;
744 
745         let payload = r#"{"id":"12345","name":"User name"}"#.as_bytes();
746 
747         let req = TestRequest::post()
748             .uri("/people")
749             .insert_header((header::CONTENT_TYPE, "application/json"))
750             .set_payload(payload)
751             .to_request();
752 
753         let result: Person = read_response_json(&app, req).await;
754         assert_eq!(&result.id, "12345");
755     }
756 
757     #[actix_rt::test]
test_body_json()758     async fn test_body_json() {
759         let app = init_service(App::new().service(web::resource("/people").route(
760             web::post().to(|person: web::Json<Person>| HttpResponse::Ok().json(person)),
761         )))
762         .await;
763 
764         let payload = r#"{"id":"12345","name":"User name"}"#.as_bytes();
765 
766         let resp = TestRequest::post()
767             .uri("/people")
768             .insert_header((header::CONTENT_TYPE, "application/json"))
769             .set_payload(payload)
770             .send_request(&app)
771             .await;
772 
773         let result: Person = read_body_json(resp).await;
774         assert_eq!(&result.name, "User name");
775     }
776 
777     #[actix_rt::test]
test_request_response_form()778     async fn test_request_response_form() {
779         let app = init_service(App::new().service(web::resource("/people").route(
780             web::post().to(|person: web::Form<Person>| HttpResponse::Ok().json(person)),
781         )))
782         .await;
783 
784         let payload = Person {
785             id: "12345".to_string(),
786             name: "User name".to_string(),
787         };
788 
789         let req = TestRequest::post()
790             .uri("/people")
791             .set_form(&payload)
792             .to_request();
793 
794         assert_eq!(req.content_type(), "application/x-www-form-urlencoded");
795 
796         let result: Person = read_response_json(&app, req).await;
797         assert_eq!(&result.id, "12345");
798         assert_eq!(&result.name, "User name");
799     }
800 
801     #[actix_rt::test]
test_request_response_json()802     async fn test_request_response_json() {
803         let app = init_service(App::new().service(web::resource("/people").route(
804             web::post().to(|person: web::Json<Person>| HttpResponse::Ok().json(person)),
805         )))
806         .await;
807 
808         let payload = Person {
809             id: "12345".to_string(),
810             name: "User name".to_string(),
811         };
812 
813         let req = TestRequest::post()
814             .uri("/people")
815             .set_json(&payload)
816             .to_request();
817 
818         assert_eq!(req.content_type(), "application/json");
819 
820         let result: Person = read_response_json(&app, req).await;
821         assert_eq!(&result.id, "12345");
822         assert_eq!(&result.name, "User name");
823     }
824 
825     #[actix_rt::test]
test_async_with_block()826     async fn test_async_with_block() {
827         async fn async_with_block() -> Result<HttpResponse, Error> {
828             let res = web::block(move || Some(4usize).ok_or("wrong")).await;
829 
830             match res {
831                 Ok(value) => Ok(HttpResponse::Ok()
832                     .content_type("text/plain")
833                     .body(format!("Async with block value: {:?}", value))),
834                 Err(_) => panic!("Unexpected"),
835             }
836         }
837 
838         let app =
839             init_service(App::new().service(web::resource("/index.html").to(async_with_block)))
840                 .await;
841 
842         let req = TestRequest::post().uri("/index.html").to_request();
843         let res = app.call(req).await.unwrap();
844         assert!(res.status().is_success());
845     }
846 
847     // allow deprecated App::data
848     #[allow(deprecated)]
849     #[actix_rt::test]
test_server_data()850     async fn test_server_data() {
851         async fn handler(data: web::Data<usize>) -> impl Responder {
852             assert_eq!(**data, 10);
853             HttpResponse::Ok()
854         }
855 
856         let app = init_service(
857             App::new()
858                 .data(10usize)
859                 .service(web::resource("/index.html").to(handler)),
860         )
861         .await;
862 
863         let req = TestRequest::post().uri("/index.html").to_request();
864         let res = app.call(req).await.unwrap();
865         assert!(res.status().is_success());
866     }
867 }
868