1
0
Fork 0
mirror of https://github.com/actix/actix-web.git synced 2024-12-21 07:36:43 +00:00

added read_response_json for testing (#776)

* added read_response_json for testing

* cleaned up

* modied docs for read_response_json

* typo in doc

* test code in doc should compile now

* use type coercion in doc

* removed generic R, replaced with Request
This commit is contained in:
Darin 2019-04-14 19:25:45 -04:00 committed by Nikolay Kim
parent d7040dc303
commit 4cc2b38059
2 changed files with 59 additions and 4 deletions

View file

@ -306,7 +306,9 @@ impl WebsocketsRequest {
} }
} else { } else {
log::trace!("Invalid connection header: {:?}", conn); log::trace!("Invalid connection header: {:?}", conn);
return Err(WsClientError::InvalidConnectionHeader(conn.clone())); return Err(WsClientError::InvalidConnectionHeader(
conn.clone(),
));
} }
} else { } else {
log::trace!("Missing connection header"); log::trace!("Missing connection header");

View file

@ -11,14 +11,16 @@ use actix_router::{Path, ResourceDef, Url};
use actix_rt::Runtime; use actix_rt::Runtime;
use actix_server_config::ServerConfig; use actix_server_config::ServerConfig;
use actix_service::{FnService, IntoNewService, NewService, Service}; use actix_service::{FnService, IntoNewService, NewService, Service};
use bytes::Bytes; use bytes::{Bytes, BytesMut};
use futures::future::{lazy, Future}; use futures::{future::{lazy, ok, Future}, stream::Stream};
use serde::de::DeserializeOwned;
use serde_json;
pub use actix_http::test::TestBuffer; pub use actix_http::test::TestBuffer;
use crate::config::{AppConfig, AppConfigInner}; use crate::config::{AppConfig, AppConfigInner};
use crate::data::RouteData; use crate::data::RouteData;
use crate::dev::{Body, Payload}; use crate::dev::{Body, MessageBody, Payload};
use crate::request::HttpRequestPool; use crate::request::HttpRequestPool;
use crate::rmap::ResourceMap; use crate::rmap::ResourceMap;
use crate::service::{ServiceRequest, ServiceResponse}; use crate::service::{ServiceRequest, ServiceResponse};
@ -363,4 +365,55 @@ impl TestRequest {
{ {
block_on(f) block_on(f)
} }
/// Helper function that returns a deserialized response body of a TestRequest
/// This function blocks the current thread until futures complete.
///
/// ```rust
/// use actix_web::{App, test, web, HttpResponse, http::header};
/// use serde::{Serialize, Deserialize};
///
/// #[derive(Serialize, Deserialize)]
/// pub struct Person { id: String, name: String }
///
/// #[test]
/// fn test_add_person() {
/// let mut app = test::init_service(App::new().service(
/// web::resource("/people")
/// .route(web::post().to(|person: web::Json<Person>| {
/// HttpResponse::Ok()
/// .json(person.into_inner())})
/// )));
///
/// let payload = r#"{"id":"12345","name":"Nikolay Kim"}"#.as_bytes();
///
/// let req = test::TestRequest::post()
/// .uri("/people")
/// .header(header::CONTENT_TYPE, "application/json")
/// .set_payload(payload)
/// .to_request();
///
/// let result: Person = test::read_response_json(&mut app, req);
/// }
/// ```
pub fn read_response_json<S, B, T>(app: &mut S, req: Request) -> T
where
S: Service<Request = Request, Response = ServiceResponse<B>, Error = Error>,
B: MessageBody,
T: DeserializeOwned,
{
block_on(app.call(req).and_then(|mut resp: ServiceResponse<B>| {
resp.take_body()
.fold(BytesMut::new(), move |mut body, chunk| {
body.extend_from_slice(&chunk);
Ok::<_, Error>(body)
})
.and_then(|body: BytesMut| {
ok(serde_json::from_slice(&body).unwrap_or_else(|_| {
panic!("read_response_json failed during deserialization")
}))
})
}))
.unwrap_or_else(|_| panic!("read_response_json failed at block_on unwrap"))
}
} }