mirror of
https://github.com/actix/actix-web.git
synced 2024-12-21 07:36:43 +00:00
add json extractor tests
This commit is contained in:
parent
7435c5e9bf
commit
c14c66d2b0
5 changed files with 105 additions and 12 deletions
|
@ -12,7 +12,7 @@ matrix:
|
||||||
- rust: beta
|
- rust: beta
|
||||||
- rust: nightly-2019-03-02
|
- rust: nightly-2019-03-02
|
||||||
allow_failures:
|
allow_failures:
|
||||||
- rust: nightly
|
- rust: nightly-2019-03-02
|
||||||
|
|
||||||
env:
|
env:
|
||||||
global:
|
global:
|
||||||
|
|
|
@ -87,8 +87,8 @@ impl ResponseError for UrlencodedError {
|
||||||
/// A set of errors that can occur during parsing json payloads
|
/// A set of errors that can occur during parsing json payloads
|
||||||
#[derive(Debug, Display, From)]
|
#[derive(Debug, Display, From)]
|
||||||
pub enum JsonPayloadError {
|
pub enum JsonPayloadError {
|
||||||
/// Payload size is bigger than allowed. (default: 256kB)
|
/// Payload size is bigger than allowed. (default: 32kB)
|
||||||
#[display(fmt = "Json payload size is bigger than allowed. (default: 256kB)")]
|
#[display(fmt = "Json payload size is bigger than allowed.")]
|
||||||
Overflow,
|
Overflow,
|
||||||
/// Content type error
|
/// Content type error
|
||||||
#[display(fmt = "Content type error")]
|
#[display(fmt = "Content type error")]
|
||||||
|
|
|
@ -288,7 +288,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
pub(crate) mod tests {
|
||||||
use actix_service::Service;
|
use actix_service::Service;
|
||||||
use bytes::{Bytes, BytesMut};
|
use bytes::{Bytes, BytesMut};
|
||||||
|
|
||||||
|
@ -322,7 +322,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait BodyTest {
|
pub(crate) trait BodyTest {
|
||||||
fn bin_ref(&self) -> &[u8];
|
fn bin_ref(&self) -> &[u8];
|
||||||
fn body(&self) -> &Body;
|
fn body(&self) -> &Body;
|
||||||
}
|
}
|
||||||
|
|
24
src/test.rs
24
src/test.rs
|
@ -5,7 +5,7 @@ use std::rc::Rc;
|
||||||
use actix_http::http::header::{Header, HeaderName, IntoHeaderValue};
|
use actix_http::http::header::{Header, HeaderName, IntoHeaderValue};
|
||||||
use actix_http::http::{HttpTryFrom, Method, Version};
|
use actix_http::http::{HttpTryFrom, Method, Version};
|
||||||
use actix_http::test::TestRequest as HttpTestRequest;
|
use actix_http::test::TestRequest as HttpTestRequest;
|
||||||
use actix_http::{PayloadStream, Request};
|
use actix_http::{Extensions, PayloadStream, Request};
|
||||||
use actix_router::{Path, ResourceDef, Url};
|
use actix_router::{Path, ResourceDef, Url};
|
||||||
use actix_rt::Runtime;
|
use actix_rt::Runtime;
|
||||||
use actix_server_config::ServerConfig;
|
use actix_server_config::ServerConfig;
|
||||||
|
@ -15,6 +15,7 @@ use cookie::Cookie;
|
||||||
use futures::future::{lazy, Future};
|
use futures::future::{lazy, Future};
|
||||||
|
|
||||||
use crate::config::{AppConfig, AppConfigInner};
|
use crate::config::{AppConfig, AppConfigInner};
|
||||||
|
use crate::data::RouteData;
|
||||||
use crate::rmap::ResourceMap;
|
use crate::rmap::ResourceMap;
|
||||||
use crate::service::{ServiceFromRequest, ServiceRequest, ServiceResponse};
|
use crate::service::{ServiceFromRequest, ServiceRequest, ServiceResponse};
|
||||||
use crate::{HttpRequest, HttpResponse};
|
use crate::{HttpRequest, HttpResponse};
|
||||||
|
@ -157,6 +158,7 @@ pub struct TestRequest {
|
||||||
req: HttpTestRequest,
|
req: HttpTestRequest,
|
||||||
rmap: ResourceMap,
|
rmap: ResourceMap,
|
||||||
config: AppConfigInner,
|
config: AppConfigInner,
|
||||||
|
route_data: Extensions,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for TestRequest {
|
impl Default for TestRequest {
|
||||||
|
@ -165,6 +167,7 @@ impl Default for TestRequest {
|
||||||
req: HttpTestRequest::default(),
|
req: HttpTestRequest::default(),
|
||||||
rmap: ResourceMap::new(ResourceDef::new("")),
|
rmap: ResourceMap::new(ResourceDef::new("")),
|
||||||
config: AppConfigInner::default(),
|
config: AppConfigInner::default(),
|
||||||
|
route_data: Extensions::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -177,6 +180,7 @@ impl TestRequest {
|
||||||
req: HttpTestRequest::default().uri(path).take(),
|
req: HttpTestRequest::default().uri(path).take(),
|
||||||
rmap: ResourceMap::new(ResourceDef::new("")),
|
rmap: ResourceMap::new(ResourceDef::new("")),
|
||||||
config: AppConfigInner::default(),
|
config: AppConfigInner::default(),
|
||||||
|
route_data: Extensions::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,6 +190,7 @@ impl TestRequest {
|
||||||
req: HttpTestRequest::default().set(hdr).take(),
|
req: HttpTestRequest::default().set(hdr).take(),
|
||||||
config: AppConfigInner::default(),
|
config: AppConfigInner::default(),
|
||||||
rmap: ResourceMap::new(ResourceDef::new("")),
|
rmap: ResourceMap::new(ResourceDef::new("")),
|
||||||
|
route_data: Extensions::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,6 +204,7 @@ impl TestRequest {
|
||||||
req: HttpTestRequest::default().header(key, value).take(),
|
req: HttpTestRequest::default().header(key, value).take(),
|
||||||
config: AppConfigInner::default(),
|
config: AppConfigInner::default(),
|
||||||
rmap: ResourceMap::new(ResourceDef::new("")),
|
rmap: ResourceMap::new(ResourceDef::new("")),
|
||||||
|
route_data: Extensions::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,6 +214,7 @@ impl TestRequest {
|
||||||
req: HttpTestRequest::default().method(Method::GET).take(),
|
req: HttpTestRequest::default().method(Method::GET).take(),
|
||||||
config: AppConfigInner::default(),
|
config: AppConfigInner::default(),
|
||||||
rmap: ResourceMap::new(ResourceDef::new("")),
|
rmap: ResourceMap::new(ResourceDef::new("")),
|
||||||
|
route_data: Extensions::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,6 +224,7 @@ impl TestRequest {
|
||||||
req: HttpTestRequest::default().method(Method::POST).take(),
|
req: HttpTestRequest::default().method(Method::POST).take(),
|
||||||
config: AppConfigInner::default(),
|
config: AppConfigInner::default(),
|
||||||
rmap: ResourceMap::new(ResourceDef::new("")),
|
rmap: ResourceMap::new(ResourceDef::new("")),
|
||||||
|
route_data: Extensions::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,12 +274,20 @@ impl TestRequest {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set route data
|
/// Set application data. This is equivalent of `App::data()` method
|
||||||
pub fn route_data<T: 'static>(self, data: T) -> Self {
|
/// for testing purpose.
|
||||||
|
pub fn app_data<T: 'static>(self, data: T) -> Self {
|
||||||
self.config.extensions.borrow_mut().insert(data);
|
self.config.extensions.borrow_mut().insert(data);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set route data. This is equivalent of `Route::data()` method
|
||||||
|
/// for testing purpose.
|
||||||
|
pub fn route_data<T: 'static>(mut self, data: T) -> Self {
|
||||||
|
self.route_data.insert(RouteData::new(data));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
/// Set request config
|
/// Set request config
|
||||||
pub(crate) fn rmap(mut self, rmap: ResourceMap) -> Self {
|
pub(crate) fn rmap(mut self, rmap: ResourceMap) -> Self {
|
||||||
|
@ -324,7 +340,7 @@ impl TestRequest {
|
||||||
Rc::new(self.rmap),
|
Rc::new(self.rmap),
|
||||||
AppConfig::new(self.config),
|
AppConfig::new(self.config),
|
||||||
);
|
);
|
||||||
ServiceFromRequest::new(req, None)
|
ServiceFromRequest::new(req, Some(Rc::new(self.route_data)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Runs the provided future, blocking the current thread until the future
|
/// Runs the provided future, blocking the current thread until the future
|
||||||
|
|
|
@ -371,6 +371,11 @@ mod tests {
|
||||||
use crate::http::header;
|
use crate::http::header;
|
||||||
use crate::test::{block_on, TestRequest};
|
use crate::test::{block_on, TestRequest};
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||||
|
struct MyObject {
|
||||||
|
name: String,
|
||||||
|
}
|
||||||
|
|
||||||
fn json_eq(err: JsonPayloadError, other: JsonPayloadError) -> bool {
|
fn json_eq(err: JsonPayloadError, other: JsonPayloadError) -> bool {
|
||||||
match err {
|
match err {
|
||||||
JsonPayloadError::Overflow => match other {
|
JsonPayloadError::Overflow => match other {
|
||||||
|
@ -385,9 +390,81 @@ mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
#[test]
|
||||||
struct MyObject {
|
fn test_responder() {
|
||||||
name: String,
|
let req = TestRequest::default().to_http_request();
|
||||||
|
|
||||||
|
let j = Json(MyObject {
|
||||||
|
name: "test".to_string(),
|
||||||
|
});
|
||||||
|
let resp = j.respond_to(&req).unwrap();
|
||||||
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
|
assert_eq!(
|
||||||
|
resp.headers().get(header::CONTENT_TYPE).unwrap(),
|
||||||
|
header::HeaderValue::from_static("application/json")
|
||||||
|
);
|
||||||
|
|
||||||
|
use crate::responder::tests::BodyTest;
|
||||||
|
assert_eq!(resp.body().bin_ref(), b"{\"name\":\"test\"}");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_extract() {
|
||||||
|
let mut req = TestRequest::default()
|
||||||
|
.header(
|
||||||
|
header::CONTENT_TYPE,
|
||||||
|
header::HeaderValue::from_static("application/json"),
|
||||||
|
)
|
||||||
|
.header(
|
||||||
|
header::CONTENT_LENGTH,
|
||||||
|
header::HeaderValue::from_static("16"),
|
||||||
|
)
|
||||||
|
.set_payload(Bytes::from_static(b"{\"name\": \"test\"}"))
|
||||||
|
.to_from();
|
||||||
|
|
||||||
|
let s = block_on(Json::<MyObject>::from_request(&mut req)).unwrap();
|
||||||
|
assert_eq!(s.name, "test");
|
||||||
|
assert_eq!(
|
||||||
|
s.into_inner(),
|
||||||
|
MyObject {
|
||||||
|
name: "test".to_string()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut req = TestRequest::default()
|
||||||
|
.header(
|
||||||
|
header::CONTENT_TYPE,
|
||||||
|
header::HeaderValue::from_static("application/json"),
|
||||||
|
)
|
||||||
|
.header(
|
||||||
|
header::CONTENT_LENGTH,
|
||||||
|
header::HeaderValue::from_static("16"),
|
||||||
|
)
|
||||||
|
.set_payload(Bytes::from_static(b"{\"name\": \"test\"}"))
|
||||||
|
.route_data(JsonConfig::default().limit(10))
|
||||||
|
.to_from();
|
||||||
|
let s = block_on(Json::<MyObject>::from_request(&mut req));
|
||||||
|
assert!(format!("{}", s.err().unwrap())
|
||||||
|
.contains("Json payload size is bigger than allowed."));
|
||||||
|
|
||||||
|
let mut req = TestRequest::default()
|
||||||
|
.header(
|
||||||
|
header::CONTENT_TYPE,
|
||||||
|
header::HeaderValue::from_static("application/json"),
|
||||||
|
)
|
||||||
|
.header(
|
||||||
|
header::CONTENT_LENGTH,
|
||||||
|
header::HeaderValue::from_static("16"),
|
||||||
|
)
|
||||||
|
.set_payload(Bytes::from_static(b"{\"name\": \"test\"}"))
|
||||||
|
.route_data(
|
||||||
|
JsonConfig::default()
|
||||||
|
.limit(10)
|
||||||
|
.error_handler(|_, _| JsonPayloadError::ContentType.into()),
|
||||||
|
)
|
||||||
|
.to_from();
|
||||||
|
let s = block_on(Json::<MyObject>::from_request(&mut req));
|
||||||
|
assert!(format!("{}", s.err().unwrap()).contains("Content type error"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Reference in a new issue