mirror of
https://github.com/actix/actix-web.git
synced 2024-12-22 08:07:18 +00:00
Add convenience functions for testing (#1401)
* Add convenience functions for testing * Fix remarks from PR and add tests * Add unpin to read_json_body * Update changelog
This commit is contained in:
parent
aaff68bf05
commit
0ad02ee0e0
2 changed files with 98 additions and 0 deletions
|
@ -14,6 +14,7 @@
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
* Add helper function for creating routes with `TRACE` method guard `web::trace()`
|
* Add helper function for creating routes with `TRACE` method guard `web::trace()`
|
||||||
|
* Add convenience functions `test::read_body_json()` and `test::TestRequest::send_request()` for testing.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|
97
src/test.rs
97
src/test.rs
|
@ -203,6 +203,54 @@ where
|
||||||
bytes.freeze()
|
bytes.freeze()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Helper function that returns a deserialized response body of a ServiceResponse.
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use actix_web::{App, test, web, HttpResponse, http::header};
|
||||||
|
/// use serde::{Serialize, Deserialize};
|
||||||
|
///
|
||||||
|
/// #[derive(Serialize, Deserialize)]
|
||||||
|
/// pub struct Person {
|
||||||
|
/// id: String,
|
||||||
|
/// name: String,
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// #[actix_rt::test]
|
||||||
|
/// async fn test_post_person() {
|
||||||
|
/// let mut app = test::init_service(
|
||||||
|
/// App::new().service(
|
||||||
|
/// web::resource("/people")
|
||||||
|
/// .route(web::post().to(|person: web::Json<Person>| async {
|
||||||
|
/// HttpResponse::Ok()
|
||||||
|
/// .json(person.into_inner())})
|
||||||
|
/// ))
|
||||||
|
/// ).await;
|
||||||
|
///
|
||||||
|
/// let payload = r#"{"id":"12345","name":"User name"}"#.as_bytes();
|
||||||
|
///
|
||||||
|
/// let resp = test::TestRequest::post()
|
||||||
|
/// .uri("/people")
|
||||||
|
/// .header(header::CONTENT_TYPE, "application/json")
|
||||||
|
/// .set_payload(payload)
|
||||||
|
/// .send_request(&mut app)
|
||||||
|
/// .await;
|
||||||
|
///
|
||||||
|
/// assert!(resp.status().is_success());
|
||||||
|
///
|
||||||
|
/// let result: Person = test::read_body_json(resp).await;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
pub async fn read_body_json<T, B>(res: ServiceResponse<B>) -> T
|
||||||
|
where
|
||||||
|
B: MessageBody + Unpin,
|
||||||
|
T: DeserializeOwned,
|
||||||
|
{
|
||||||
|
let body = read_body(res).await;
|
||||||
|
|
||||||
|
serde_json::from_slice(&body)
|
||||||
|
.unwrap_or_else(|_| panic!("read_response_json failed during deserialization"))
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn load_stream<S>(mut stream: S) -> Result<Bytes, Error>
|
pub async fn load_stream<S>(mut stream: S) -> Result<Bytes, Error>
|
||||||
where
|
where
|
||||||
S: Stream<Item = Result<Bytes, Error>> + Unpin,
|
S: Stream<Item = Result<Bytes, Error>> + Unpin,
|
||||||
|
@ -527,6 +575,16 @@ impl TestRequest {
|
||||||
|
|
||||||
(req, payload)
|
(req, payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Complete request creation, calls service and waits for response future completion.
|
||||||
|
pub async fn send_request<S, B, E>(self, app: &mut S) -> S::Response
|
||||||
|
where
|
||||||
|
S: Service<Request = Request, Response = ServiceResponse<B>, Error = E>,
|
||||||
|
E: std::fmt::Debug
|
||||||
|
{
|
||||||
|
let req = self.to_request();
|
||||||
|
call_service(app, req).await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Start test server with default configuration
|
/// Start test server with default configuration
|
||||||
|
@ -1041,6 +1099,23 @@ mod tests {
|
||||||
assert_eq!(result, Bytes::from_static(b"welcome!"));
|
assert_eq!(result, Bytes::from_static(b"welcome!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn test_send_request() {
|
||||||
|
let mut app =
|
||||||
|
init_service(App::new().service(web::resource("/index.html").route(
|
||||||
|
web::get().to(|| async { HttpResponse::Ok().body("welcome!") }),
|
||||||
|
)))
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let resp = TestRequest::get()
|
||||||
|
.uri("/index.html")
|
||||||
|
.send_request(&mut app)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let result = read_body(resp).await;
|
||||||
|
assert_eq!(result, Bytes::from_static(b"welcome!"));
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct Person {
|
pub struct Person {
|
||||||
id: String,
|
id: String,
|
||||||
|
@ -1068,6 +1143,28 @@ mod tests {
|
||||||
assert_eq!(&result.id, "12345");
|
assert_eq!(&result.id, "12345");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn test_body_json() {
|
||||||
|
let mut app = init_service(App::new().service(web::resource("/people").route(
|
||||||
|
web::post().to(|person: web::Json<Person>| {
|
||||||
|
async { HttpResponse::Ok().json(person.into_inner()) }
|
||||||
|
}),
|
||||||
|
)))
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let payload = r#"{"id":"12345","name":"User name"}"#.as_bytes();
|
||||||
|
|
||||||
|
let resp = TestRequest::post()
|
||||||
|
.uri("/people")
|
||||||
|
.header(header::CONTENT_TYPE, "application/json")
|
||||||
|
.set_payload(payload)
|
||||||
|
.send_request(&mut app)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let result: Person = read_body_json(resp).await;
|
||||||
|
assert_eq!(&result.name, "User name");
|
||||||
|
}
|
||||||
|
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
async fn test_request_response_form() {
|
async fn test_request_response_form() {
|
||||||
let mut app = init_service(App::new().service(web::resource("/people").route(
|
let mut app = init_service(App::new().service(web::resource("/people").route(
|
||||||
|
|
Loading…
Reference in a new issue