1
0
Fork 0
mirror of https://github.com/actix/actix-web.git synced 2024-06-12 02:09:36 +00:00

provide block_on function for testing purpose

This commit is contained in:
Nikolay Kim 2019-03-04 13:25:35 -08:00
parent e442ddb167
commit bd4124587a
8 changed files with 207 additions and 175 deletions

View file

@ -46,6 +46,7 @@ flate2-rust = ["flate2/rust_backend"]
actix-codec = "0.1.0"
actix-service = "0.3.0"
actix-utils = "0.3.0"
actix-rt = "0.1.0"
actix-http = { git = "https://github.com/actix/actix-http.git" }
actix-router = { git = "https://github.com/actix/actix-net.git" }
@ -69,7 +70,6 @@ brotli2 = { version="^0.3.2", optional = true }
flate2 = { version="^1.0.2", optional = true, default-features = false }
[dev-dependencies]
actix-rt = "0.1.0"
actix-server = { version="0.3.0", features=["ssl"] }
actix-http = { git = "https://github.com/actix/actix-http.git", features=["ssl"] }
actix-http-test = { git = "https://github.com/actix/actix-http.git", features=["ssl"] }

View file

@ -924,85 +924,95 @@ where
#[cfg(test)]
mod tests {
use actix_http::http::StatusCode;
use actix_http::http::{Method, StatusCode};
use super::*;
use crate::test::TestRequest;
use crate::{HttpResponse, State};
use crate::test::{block_on, TestRequest};
use crate::{web, HttpResponse, State};
#[test]
fn test_default_resource() {
let mut rt = actix_rt::Runtime::new().unwrap();
let app = App::new()
.resource("/test", |r| r.to(|| HttpResponse::Ok()))
.into_new_service();
let mut srv = rt.block_on(app.new_service(&())).unwrap();
let mut srv = block_on(app.new_service(&())).unwrap();
let req = TestRequest::with_uri("/test").to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::OK);
let req = TestRequest::with_uri("/blah").to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
let app = App::new()
.resource("/test", |r| r.to(|| HttpResponse::Ok()))
.resource("/test2", |r| {
r.default_resource(|r| r.to(|| HttpResponse::Created()))
.route(web::get().to(|| HttpResponse::Ok()))
})
.default_resource(|r| r.to(|| HttpResponse::MethodNotAllowed()))
.into_new_service();
let mut srv = rt.block_on(app.new_service(&())).unwrap();
let mut srv = block_on(app.new_service(&())).unwrap();
let req = TestRequest::with_uri("/blah").to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::METHOD_NOT_ALLOWED);
let req = TestRequest::with_uri("/test2").to_request();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::OK);
let req = TestRequest::with_uri("/test2")
.method(Method::POST)
.to_request();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::CREATED);
}
#[test]
fn test_state() {
let mut rt = actix_rt::Runtime::new().unwrap();
let app = App::new()
.state(10usize)
.resource("/", |r| r.to(|_: State<usize>| HttpResponse::Ok()))
.into_new_service();
let mut srv = rt.block_on(app.new_service(&())).unwrap();
let mut srv = block_on(app.new_service(&())).unwrap();
let req = TestRequest::default().to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::OK);
let app = App::new()
.state(10u32)
.resource("/", |r| r.to(|_: State<usize>| HttpResponse::Ok()))
.into_new_service();
let mut srv = rt.block_on(app.new_service(&())).unwrap();
let mut srv = block_on(app.new_service(&())).unwrap();
let req = TestRequest::default().to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
}
#[test]
fn test_state_factory() {
let mut rt = actix_rt::Runtime::new().unwrap();
let app = App::new()
.state_factory(|| Ok::<_, ()>(10usize))
.resource("/", |r| r.to(|_: State<usize>| HttpResponse::Ok()))
.into_new_service();
let mut srv = rt.block_on(app.new_service(&())).unwrap();
let mut srv = block_on(app.new_service(&())).unwrap();
let req = TestRequest::default().to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::OK);
let app = App::new()
.state_factory(|| Ok::<_, ()>(10u32))
.resource("/", |r| r.to(|_: State<usize>| HttpResponse::Ok()))
.into_new_service();
let mut srv = rt.block_on(app.new_service(&())).unwrap();
let mut srv = block_on(app.new_service(&())).unwrap();
let req = TestRequest::default().to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
}

View file

@ -1152,7 +1152,7 @@ mod tests {
use serde_derive::Deserialize;
use super::*;
use crate::test::TestRequest;
use crate::test::{block_on, TestRequest};
#[derive(Deserialize, Debug, PartialEq)]
struct Info {
@ -1161,29 +1161,26 @@ mod tests {
#[test]
fn test_bytes() {
let mut rt = actix_rt::Runtime::new().unwrap();
let mut req = TestRequest::with_header(header::CONTENT_LENGTH, "11")
.set_payload(Bytes::from_static(b"hello=world"))
.to_from();
let s = rt.block_on(Bytes::from_request(&mut req)).unwrap();
let s = block_on(Bytes::from_request(&mut req)).unwrap();
assert_eq!(s, Bytes::from_static(b"hello=world"));
}
#[test]
fn test_string() {
let mut rt = actix_rt::Runtime::new().unwrap();
let mut req = TestRequest::with_header(header::CONTENT_LENGTH, "11")
.set_payload(Bytes::from_static(b"hello=world"))
.to_from();
let s = rt.block_on(String::from_request(&mut req)).unwrap();
let s = block_on(String::from_request(&mut req)).unwrap();
assert_eq!(s, "hello=world");
}
#[test]
fn test_form() {
let mut rt = actix_rt::Runtime::new().unwrap();
let mut req = TestRequest::with_header(
header::CONTENT_TYPE,
"application/x-www-form-urlencoded",
@ -1192,13 +1189,12 @@ mod tests {
.set_payload(Bytes::from_static(b"hello=world"))
.to_from();
let s = rt.block_on(Form::<Info>::from_request(&mut req)).unwrap();
let s = block_on(Form::<Info>::from_request(&mut req)).unwrap();
assert_eq!(s.hello, "world");
}
#[test]
fn test_option() {
let mut rt = actix_rt::Runtime::new().unwrap();
let mut req = TestRequest::with_header(
header::CONTENT_TYPE,
"application/x-www-form-urlencoded",
@ -1206,9 +1202,7 @@ mod tests {
.config(FormConfig::default().limit(4096))
.to_from();
let r = rt
.block_on(Option::<Form<Info>>::from_request(&mut req))
.unwrap();
let r = block_on(Option::<Form<Info>>::from_request(&mut req)).unwrap();
assert_eq!(r, None);
let mut req = TestRequest::with_header(
@ -1219,9 +1213,7 @@ mod tests {
.set_payload(Bytes::from_static(b"hello=world"))
.to_from();
let r = rt
.block_on(Option::<Form<Info>>::from_request(&mut req))
.unwrap();
let r = block_on(Option::<Form<Info>>::from_request(&mut req)).unwrap();
assert_eq!(
r,
Some(Form(Info {
@ -1237,15 +1229,12 @@ mod tests {
.set_payload(Bytes::from_static(b"bye=world"))
.to_from();
let r = rt
.block_on(Option::<Form<Info>>::from_request(&mut req))
.unwrap();
let r = block_on(Option::<Form<Info>>::from_request(&mut req)).unwrap();
assert_eq!(r, None);
}
#[test]
fn test_result() {
let mut rt = actix_rt::Runtime::new().unwrap();
let mut req = TestRequest::with_header(
header::CONTENT_TYPE,
"application/x-www-form-urlencoded",
@ -1254,8 +1243,7 @@ mod tests {
.set_payload(Bytes::from_static(b"hello=world"))
.to_from();
let r = rt
.block_on(Result::<Form<Info>, Error>::from_request(&mut req))
let r = block_on(Result::<Form<Info>, Error>::from_request(&mut req))
.unwrap()
.unwrap();
assert_eq!(
@ -1273,9 +1261,7 @@ mod tests {
.set_payload(Bytes::from_static(b"bye=world"))
.to_from();
let r = rt
.block_on(Result::<Form<Info>, Error>::from_request(&mut req))
.unwrap();
let r = block_on(Result::<Form<Info>, Error>::from_request(&mut req)).unwrap();
assert!(r.is_err());
}
@ -1361,25 +1347,19 @@ mod tests {
#[test]
fn test_tuple_extract() {
let mut rt = actix_rt::Runtime::new().unwrap();
let resource = ResourceDef::new("/{key}/{value}/");
let mut req = TestRequest::with_uri("/name/user1/?id=test").to_from();
resource.match_path(req.match_info_mut());
let res = rt
.block_on(<(Path<(String, String)>,)>::from_request(&mut req))
.unwrap();
let res = block_on(<(Path<(String, String)>,)>::from_request(&mut req)).unwrap();
assert_eq!((res.0).0, "name");
assert_eq!((res.0).1, "user1");
let res = rt
.block_on(
<(Path<(String, String)>, Path<(String, String)>)>::from_request(
&mut req,
),
)
.unwrap();
let res = block_on(
<(Path<(String, String)>, Path<(String, String)>)>::from_request(&mut req),
)
.unwrap();
assert_eq!((res.0).0, "name");
assert_eq!((res.0).1, "user1");
assert_eq!((res.1).0, "name");

View file

@ -239,8 +239,7 @@ mod tests {
#[test]
fn test_header() {
let req = TestRequest::with_header(header::TRANSFER_ENCODING, "chunked")
.finish()
.into_request();
.to_http_request();
let pred = Header("transfer-encoding", "chunked");
assert!(pred.check(&req));
@ -270,44 +269,55 @@ mod tests {
#[test]
fn test_methods() {
let req = TestRequest::default().finish().into_request();
let req = TestRequest::default().to_http_request();
let req2 = TestRequest::default()
.method(Method::POST)
.finish()
.into_request();
.to_http_request();
assert!(Get().check(&req));
assert!(!Get().check(&req2));
assert!(Post().check(&req2));
assert!(!Post().check(&req));
let r = TestRequest::default().method(Method::PUT).finish();
assert!(Put().check(&r,));
assert!(!Put().check(&req,));
let r = TestRequest::default().method(Method::PUT).to_http_request();
assert!(Put().check(&r));
assert!(!Put().check(&req));
let r = TestRequest::default().method(Method::DELETE).finish();
assert!(Delete().check(&r,));
assert!(!Delete().check(&req,));
let r = TestRequest::default()
.method(Method::DELETE)
.to_http_request();
assert!(Delete().check(&r));
assert!(!Delete().check(&req));
let r = TestRequest::default().method(Method::HEAD).finish();
assert!(Head().check(&r,));
assert!(!Head().check(&req,));
let r = TestRequest::default()
.method(Method::HEAD)
.to_http_request();
assert!(Head().check(&r));
assert!(!Head().check(&req));
let r = TestRequest::default().method(Method::OPTIONS).finish();
assert!(Options().check(&r,));
assert!(!Options().check(&req,));
let r = TestRequest::default()
.method(Method::OPTIONS)
.to_http_request();
assert!(Options().check(&r));
assert!(!Options().check(&req));
let r = TestRequest::default().method(Method::CONNECT).finish();
assert!(Connect().check(&r,));
assert!(!Connect().check(&req,));
let r = TestRequest::default()
.method(Method::CONNECT)
.to_http_request();
assert!(Connect().check(&r));
assert!(!Connect().check(&req));
let r = TestRequest::default().method(Method::PATCH).finish();
assert!(Patch().check(&r,));
assert!(!Patch().check(&req,));
let r = TestRequest::default()
.method(Method::PATCH)
.to_http_request();
assert!(Patch().check(&r));
assert!(!Patch().check(&req));
let r = TestRequest::default().method(Method::TRACE).finish();
assert!(Trace().check(&r,));
assert!(!Trace().check(&req,));
let r = TestRequest::default()
.method(Method::TRACE)
.to_http_request();
assert!(Trace().check(&r));
assert!(!Trace().check(&req));
}
#[test]
@ -316,13 +326,13 @@ mod tests {
.method(Method::TRACE)
.to_http_request();
assert!(Not(Get()).check(&r,));
assert!(!Not(Trace()).check(&r,));
assert!(Not(Get()).check(&r));
assert!(!Not(Trace()).check(&r));
assert!(All(Trace()).and(Trace()).check(&r,));
assert!(!All(Get()).and(Trace()).check(&r,));
assert!(All(Trace()).and(Trace()).check(&r));
assert!(!All(Get()).and(Trace()).check(&r));
assert!(Any(Get()).or(Trace()).check(&r,));
assert!(!Any(Get()).or(Get()).check(&r,));
assert!(Any(Get()).or(Trace()).check(&r));
assert!(!Any(Get()).or(Get()).check(&r));
}
}

View file

@ -138,39 +138,37 @@ mod tests {
use actix_service::FnService;
use super::*;
use crate::test::TestRequest;
use crate::test::{block_on, TestRequest};
use crate::{HttpResponse, ServiceRequest};
#[test]
fn test_default_headers() {
let mut rt = actix_rt::Runtime::new().unwrap();
let mut mw = DefaultHeaders::new().header(CONTENT_TYPE, "0001");
let mut srv = FnService::new(|req: ServiceRequest<_>| {
req.into_response(HttpResponse::Ok().finish())
});
let req = TestRequest::default().finish();
let resp = rt.block_on(mw.call(req, &mut srv)).unwrap();
let req = TestRequest::default().to_service();
let resp = block_on(mw.call(req, &mut srv)).unwrap();
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001");
let req = TestRequest::default().finish();
let req = TestRequest::default().to_service();
let mut srv = FnService::new(|req: ServiceRequest<_>| {
req.into_response(HttpResponse::Ok().header(CONTENT_TYPE, "0002").finish())
});
let resp = rt.block_on(mw.call(req, &mut srv)).unwrap();
let resp = block_on(mw.call(req, &mut srv)).unwrap();
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0002");
}
#[test]
fn test_content_type() {
let mut rt = actix_rt::Runtime::new().unwrap();
let mut mw = DefaultHeaders::new().content_type();
let mut srv = FnService::new(|req: ServiceRequest<_>| {
req.into_response(HttpResponse::Ok().finish())
});
let req = TestRequest::default().finish();
let resp = rt.block_on(mw.call(req, &mut srv)).unwrap();
let req = TestRequest::default().to_service();
let resp = block_on(mw.call(req, &mut srv)).unwrap();
assert_eq!(
resp.headers().get(CONTENT_TYPE).unwrap(),
"application/octet-stream"

View file

@ -286,19 +286,18 @@ mod tests {
#[test]
fn test_option_responder() {
let mut rt = actix_rt::Runtime::new().unwrap();
let app = App::new()
.resource("/none", |r| r.to(|| -> Option<&'static str> { None }))
.resource("/some", |r| r.to(|| Some("some")))
.into_new_service();
let mut srv = rt.block_on(app.new_service(&())).unwrap();
let mut srv = TestRequest::block_on(app.new_service(&())).unwrap();
let req = TestRequest::with_uri("/none").to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = TestRequest::block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
let req = TestRequest::with_uri("/some").to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = TestRequest::block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::OK);
match resp.body() {
ResponseBody::Body(Body::Bytes(ref b)) => {

View file

@ -32,14 +32,14 @@ type BoxedResponse = Box<Future<Item = ServiceResponse, Error = ()>>;
/// `Path` extractor also is able to extract scope level variable segments.
///
/// ```rust
/// use actix_web::{App, HttpResponse};
/// use actix_web::{web, App, HttpResponse};
///
/// fn main() {
/// let app = App::new().scope("/{project_id}/", |scope| {
/// scope
/// .resource("/path1", |r| r.to(|| HttpResponse::Ok()))
/// .resource("/path2", |r| r.to(|| HttpResponse::Ok()))
/// .resource("/path3", |r| r.to(|| HttpResponse::MethodNotAllowed()))
/// .resource("/path2", |r| r.route(web::get().to(|| HttpResponse::Ok())))
/// .resource("/path3", |r| r.route(web::head().to(|| HttpResponse::MethodNotAllowed())))
/// });
/// }
/// ```
@ -512,27 +512,25 @@ mod tests {
use actix_service::{IntoNewService, NewService, Service};
use bytes::Bytes;
use crate::test::TestRequest;
use crate::test::{block_on, TestRequest};
use crate::{guard, web, App, HttpRequest, HttpResponse};
#[test]
fn test_scope() {
let mut rt = actix_rt::Runtime::new().unwrap();
let app = App::new()
.scope("/app", |scope| {
scope.resource("/path1", |r| r.to(|| HttpResponse::Ok()))
})
.into_new_service();
let mut srv = rt.block_on(app.new_service(&())).unwrap();
let mut srv = block_on(app.new_service(&())).unwrap();
let req = TestRequest::with_uri("/app/path1").to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::OK);
}
#[test]
fn test_scope_root() {
let mut rt = actix_rt::Runtime::new().unwrap();
let app = App::new()
.scope("/app", |scope| {
scope
@ -540,58 +538,55 @@ mod tests {
.resource("/", |r| r.to(|| HttpResponse::Created()))
})
.into_new_service();
let mut srv = rt.block_on(app.new_service(&())).unwrap();
let mut srv = block_on(app.new_service(&())).unwrap();
let req = TestRequest::with_uri("/app").to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::OK);
let req = TestRequest::with_uri("/app/").to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::CREATED);
}
#[test]
fn test_scope_root2() {
let mut rt = actix_rt::Runtime::new().unwrap();
let app = App::new()
.scope("/app/", |scope| {
scope.resource("", |r| r.to(|| HttpResponse::Ok()))
})
.into_new_service();
let mut srv = rt.block_on(app.new_service(&())).unwrap();
let mut srv = block_on(app.new_service(&())).unwrap();
let req = TestRequest::with_uri("/app").to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
let req = TestRequest::with_uri("/app/").to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::OK);
}
#[test]
fn test_scope_root3() {
let mut rt = actix_rt::Runtime::new().unwrap();
let app = App::new()
.scope("/app/", |scope| {
scope.resource("/", |r| r.to(|| HttpResponse::Ok()))
})
.into_new_service();
let mut srv = rt.block_on(app.new_service(&())).unwrap();
let mut srv = block_on(app.new_service(&())).unwrap();
let req = TestRequest::with_uri("/app").to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
let req = TestRequest::with_uri("/app/").to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
}
#[test]
fn test_scope_route() {
let mut rt = actix_rt::Runtime::new().unwrap();
let app = App::new()
.scope("app", |scope| {
scope.resource("/path1", |r| {
@ -600,28 +595,27 @@ mod tests {
})
})
.into_new_service();
let mut srv = rt.block_on(app.new_service(&())).unwrap();
let mut srv = block_on(app.new_service(&())).unwrap();
let req = TestRequest::with_uri("/app/path1").to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::OK);
let req = TestRequest::with_uri("/app/path1")
.method(Method::DELETE)
.to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::OK);
let req = TestRequest::with_uri("/app/path1")
.method(Method::POST)
.to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
}
#[test]
fn test_scope_route_without_leading_slash() {
let mut rt = actix_rt::Runtime::new().unwrap();
let app = App::new()
.scope("app", |scope| {
scope.resource("path1", |r| {
@ -630,28 +624,27 @@ mod tests {
})
})
.into_new_service();
let mut srv = rt.block_on(app.new_service(&())).unwrap();
let mut srv = block_on(app.new_service(&())).unwrap();
let req = TestRequest::with_uri("/app/path1").to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::OK);
let req = TestRequest::with_uri("/app/path1")
.method(Method::DELETE)
.to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::OK);
let req = TestRequest::with_uri("/app/path1")
.method(Method::POST)
.to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
}
#[test]
fn test_scope_guard() {
let mut rt = actix_rt::Runtime::new().unwrap();
let app = App::new()
.scope("/app", |scope| {
scope
@ -659,24 +652,23 @@ mod tests {
.resource("/path1", |r| r.to(|| HttpResponse::Ok()))
})
.into_new_service();
let mut srv = rt.block_on(app.new_service(&())).unwrap();
let mut srv = block_on(app.new_service(&())).unwrap();
let req = TestRequest::with_uri("/app/path1")
.method(Method::POST)
.to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
let req = TestRequest::with_uri("/app/path1")
.method(Method::GET)
.to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::OK);
}
#[test]
fn test_scope_variable_segment() {
let mut rt = actix_rt::Runtime::new().unwrap();
let app = App::new()
.scope("/ab-{project}", |scope| {
scope.resource("/path1", |r| {
@ -687,10 +679,10 @@ mod tests {
})
})
.into_new_service();
let mut srv = rt.block_on(app.new_service(&())).unwrap();
let mut srv = block_on(app.new_service(&())).unwrap();
let req = TestRequest::with_uri("/ab-project1/path1").to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::OK);
match resp.body() {
@ -702,13 +694,12 @@ mod tests {
}
let req = TestRequest::with_uri("/aa-project1/path1").to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
}
#[test]
fn test_nested_scope() {
let mut rt = actix_rt::Runtime::new().unwrap();
let app = App::new()
.scope("/app", |scope| {
scope.nested("/t1", |scope| {
@ -716,16 +707,15 @@ mod tests {
})
})
.into_new_service();
let mut srv = rt.block_on(app.new_service(&())).unwrap();
let mut srv = block_on(app.new_service(&())).unwrap();
let req = TestRequest::with_uri("/app/t1/path1").to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::CREATED);
}
#[test]
fn test_nested_scope_no_slash() {
let mut rt = actix_rt::Runtime::new().unwrap();
let app = App::new()
.scope("/app", |scope| {
scope.nested("t1", |scope| {
@ -733,16 +723,15 @@ mod tests {
})
})
.into_new_service();
let mut srv = rt.block_on(app.new_service(&())).unwrap();
let mut srv = block_on(app.new_service(&())).unwrap();
let req = TestRequest::with_uri("/app/t1/path1").to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::CREATED);
}
#[test]
fn test_nested_scope_root() {
let mut rt = actix_rt::Runtime::new().unwrap();
let app = App::new()
.scope("/app", |scope| {
scope.nested("/t1", |scope| {
@ -752,20 +741,19 @@ mod tests {
})
})
.into_new_service();
let mut srv = rt.block_on(app.new_service(&())).unwrap();
let mut srv = block_on(app.new_service(&())).unwrap();
let req = TestRequest::with_uri("/app/t1").to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::OK);
let req = TestRequest::with_uri("/app/t1/").to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::CREATED);
}
#[test]
fn test_nested_scope_filter() {
let mut rt = actix_rt::Runtime::new().unwrap();
let app = App::new()
.scope("/app", |scope| {
scope.nested("/t1", |scope| {
@ -775,24 +763,23 @@ mod tests {
})
})
.into_new_service();
let mut srv = rt.block_on(app.new_service(&())).unwrap();
let mut srv = block_on(app.new_service(&())).unwrap();
let req = TestRequest::with_uri("/app/t1/path1")
.method(Method::POST)
.to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
let req = TestRequest::with_uri("/app/t1/path1")
.method(Method::GET)
.to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::OK);
}
#[test]
fn test_nested_scope_with_variable_segment() {
let mut rt = actix_rt::Runtime::new().unwrap();
let app = App::new()
.scope("/app", |scope| {
scope.nested("/{project_id}", |scope| {
@ -807,10 +794,10 @@ mod tests {
})
})
.into_new_service();
let mut srv = rt.block_on(app.new_service(&())).unwrap();
let mut srv = block_on(app.new_service(&())).unwrap();
let req = TestRequest::with_uri("/app/project_1/path1").to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::CREATED);
match resp.body() {
@ -824,7 +811,6 @@ mod tests {
#[test]
fn test_nested2_scope_with_variable_segment() {
let mut rt = actix_rt::Runtime::new().unwrap();
let app = App::new()
.scope("/app", |scope| {
scope.nested("/{project}", |scope| {
@ -842,10 +828,10 @@ mod tests {
})
})
.into_new_service();
let mut srv = rt.block_on(app.new_service(&())).unwrap();
let mut srv = block_on(app.new_service(&())).unwrap();
let req = TestRequest::with_uri("/app/test/1/path1").to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::CREATED);
match resp.body() {
@ -857,13 +843,12 @@ mod tests {
}
let req = TestRequest::with_uri("/app/test/1/path2").to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
}
#[test]
fn test_default_resource() {
let mut rt = actix_rt::Runtime::new().unwrap();
let app = App::new()
.scope("/app", |scope| {
scope
@ -871,20 +856,19 @@ mod tests {
.default_resource(|r| r.to(|| HttpResponse::BadRequest()))
})
.into_new_service();
let mut srv = rt.block_on(app.new_service(&())).unwrap();
let mut srv = block_on(app.new_service(&())).unwrap();
let req = TestRequest::with_uri("/app/path2").to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
let req = TestRequest::with_uri("/path2").to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
}
#[test]
fn test_default_resource_propagation() {
let mut rt = actix_rt::Runtime::new().unwrap();
let app = App::new()
.scope("/app1", |scope| {
scope.default_resource(|r| r.to(|| HttpResponse::BadRequest()))
@ -892,18 +876,18 @@ mod tests {
.scope("/app2", |scope| scope)
.default_resource(|r| r.to(|| HttpResponse::MethodNotAllowed()))
.into_new_service();
let mut srv = rt.block_on(app.new_service(&())).unwrap();
let mut srv = block_on(app.new_service(&())).unwrap();
let req = TestRequest::with_uri("/non-exist").to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::METHOD_NOT_ALLOWED);
let req = TestRequest::with_uri("/app1/non-exist").to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
let req = TestRequest::with_uri("/app2/non-exist").to_request();
let resp = rt.block_on(srv.call(req)).unwrap();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::METHOD_NOT_ALLOWED);
}
}

View file

@ -1,4 +1,5 @@
//! Various helpers for Actix applications to use during testing.
use std::cell::RefCell;
use std::rc::Rc;
use actix_http::http::header::{Header, HeaderName, IntoHeaderValue};
@ -6,16 +7,47 @@ use actix_http::http::{HttpTryFrom, Method, Version};
use actix_http::test::TestRequest as HttpTestRequest;
use actix_http::{Extensions, PayloadStream, Request};
use actix_router::{Path, Url};
use actix_rt::Runtime;
use bytes::Bytes;
use futures::Future;
use crate::request::HttpRequest;
use crate::service::{ServiceFromRequest, ServiceRequest};
/// Test `Request` builder
thread_local! {
static RT: RefCell<Runtime> = {
RefCell::new(Runtime::new().unwrap())
};
}
/// Runs the provided future, blocking the current thread until the future
/// completes.
///
/// This function can be used to synchronously block the current thread
/// until the provided `future` has resolved either successfully or with an
/// error. The result of the future is then returned from this function
/// call.
///
/// Note that this function is intended to be used only for testing purpose.
/// This function panics on nested call.
pub fn block_on<F>(f: F) -> Result<F::Item, F::Error>
where
F: Future,
{
RT.with(move |rt| rt.borrow_mut().block_on(f))
}
/// Test `Request` builder.
///
/// For unit testing, actix provides a request builder type and a simple handler runner. TestRequest implements a builder-like pattern.
/// You can generate various types of request via TestRequest's methods:
/// * `TestRequest::to_request` creates `actix_http::Request` instance.
/// * `TestRequest::to_service` creates `ServiceRequest` instance, which is used for testing middlewares and chain adapters.
/// * `TestRequest::to_from` creates `ServiceFromRequest` instance, which is used for testing extractors.
/// * `TestRequest::to_http_request` creates `HttpRequest` instance, which is used for testing handlers.
///
/// ```rust,ignore
/// # use actix_web::*;
/// use actix_web::test::TestRequest;
/// use actix_web::test;
///
/// fn index(req: HttpRequest) -> HttpResponse {
/// if let Some(hdr) = req.headers().get(header::CONTENT_TYPE) {
@ -26,12 +58,14 @@ use crate::service::{ServiceFromRequest, ServiceRequest};
/// }
///
/// fn main() {
/// let resp = TestRequest::with_header("content-type", "text/plain")
/// .run(&index)
/// .unwrap();
/// let req = test::TestRequest::with_header("content-type", "text/plain")
/// .to_http_request();
///
/// let resp = test::block_on(index(req));
/// assert_eq!(resp.status(), StatusCode::OK);
///
/// let resp = TestRequest::default().run(&index).unwrap();
/// let req = test::TestRequest::default().to_http_request();
/// let resp = test::block_on(index(req));
/// assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
/// }
/// ```
@ -125,7 +159,7 @@ impl TestRequest {
}
/// Complete request creation and generate `ServiceRequest` instance
pub fn finish(mut self) -> ServiceRequest<PayloadStream> {
pub fn to_service(mut self) -> ServiceRequest<PayloadStream> {
let req = self.req.finish();
ServiceRequest::new(
@ -163,4 +197,21 @@ impl TestRequest {
);
ServiceFromRequest::new(req, None)
}
/// Runs the provided future, blocking the current thread until the future
/// completes.
///
/// This function can be used to synchronously block the current thread
/// until the provided `future` has resolved either successfully or with an
/// error. The result of the future is then returned from this function
/// call.
///
/// Note that this function is intended to be used only for testing purpose.
/// This function panics on nested call.
pub fn block_on<F>(f: F) -> Result<F::Item, F::Error>
where
F: Future,
{
block_on(f)
}
}