mirror of
https://github.com/tokio-rs/axum.git
synced 2026-08-27 00:00:24 +02:00
Start writing more tests
This commit is contained in:
+3
-182
@@ -1,15 +1,3 @@
|
||||
/*
|
||||
|
||||
Improvements to make:
|
||||
|
||||
Support extracting headers, perhaps via `headers::Header`?
|
||||
|
||||
Improve compile times with lots of routes, can we box and combine routers?
|
||||
|
||||
Tests
|
||||
|
||||
*/
|
||||
|
||||
use self::{
|
||||
body::Body,
|
||||
routing::{EmptyRouter, RouteAt},
|
||||
@@ -33,6 +21,9 @@ pub mod routing;
|
||||
|
||||
mod error;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub use self::error::Error;
|
||||
|
||||
pub fn app() -> App<EmptyRouter> {
|
||||
@@ -139,173 +130,3 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#![allow(warnings)]
|
||||
use super::*;
|
||||
use crate::handler::Handler;
|
||||
use http::{Method, Request, StatusCode};
|
||||
use hyper::Server;
|
||||
use serde::Deserialize;
|
||||
use std::time::Duration;
|
||||
use std::{fmt, net::SocketAddr, sync::Arc};
|
||||
use tower::{
|
||||
layer::util::Identity, make::Shared, service_fn, timeout::TimeoutLayer, ServiceBuilder,
|
||||
ServiceExt,
|
||||
};
|
||||
use tower_http::{
|
||||
add_extension::AddExtensionLayer,
|
||||
compression::CompressionLayer,
|
||||
trace::{Trace, TraceLayer},
|
||||
};
|
||||
|
||||
#[tokio::test]
|
||||
async fn basic() {
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct Pagination {
|
||||
page: usize,
|
||||
per_page: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct UsersCreate {
|
||||
username: String,
|
||||
}
|
||||
|
||||
async fn root(_: Request<Body>) -> Result<Response<Body>, Error> {
|
||||
Ok(Response::new(Body::from("Hello, World!")))
|
||||
}
|
||||
|
||||
async fn large_static_file(
|
||||
_: Request<Body>,
|
||||
body: extract::BytesMaxLength<{ 1024 * 500 }>,
|
||||
) -> Result<Response<Body>, Error> {
|
||||
Ok(Response::new(Body::empty()))
|
||||
}
|
||||
|
||||
let app = app()
|
||||
// routes with functions
|
||||
.at("/")
|
||||
.get(root)
|
||||
// routes with closures
|
||||
.at("/users")
|
||||
.get(
|
||||
|_: Request<Body>, pagination: extract::Query<Pagination>| async {
|
||||
let pagination = pagination.into_inner();
|
||||
assert_eq!(pagination.page, 1);
|
||||
assert_eq!(pagination.per_page, 30);
|
||||
Ok::<_, Error>("users#index".to_string())
|
||||
},
|
||||
)
|
||||
.post(
|
||||
|_: Request<Body>,
|
||||
payload: extract::Json<UsersCreate>,
|
||||
_state: extract::Extension<Arc<State>>| async {
|
||||
let payload = payload.into_inner();
|
||||
assert_eq!(payload.username, "bob");
|
||||
Ok::<_, Error>(response::Json(
|
||||
serde_json::json!({ "username": payload.username }),
|
||||
))
|
||||
},
|
||||
)
|
||||
// routes with a service
|
||||
.at("/service")
|
||||
.get_service(service_fn(root))
|
||||
// routes with layers applied
|
||||
.at("/large-static-file")
|
||||
.get(
|
||||
large_static_file.layer(
|
||||
ServiceBuilder::new()
|
||||
.layer(TimeoutLayer::new(Duration::from_secs(30)))
|
||||
.layer(CompressionLayer::new())
|
||||
.into_inner(),
|
||||
),
|
||||
)
|
||||
.into_service();
|
||||
|
||||
// state shared by all routes, could hold db connection etc
|
||||
struct State {}
|
||||
|
||||
let state = Arc::new(State {});
|
||||
|
||||
// can add more middleware
|
||||
let mut app = ServiceBuilder::new()
|
||||
.layer(AddExtensionLayer::new(state))
|
||||
.layer(TraceLayer::new_for_http())
|
||||
.service(app);
|
||||
|
||||
let res = app
|
||||
.ready()
|
||||
.await
|
||||
.unwrap()
|
||||
.call(
|
||||
Request::builder()
|
||||
.method(Method::GET)
|
||||
.uri("/")
|
||||
.body(Body::empty())
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(res.status(), StatusCode::OK);
|
||||
assert_eq!(body_to_string(res).await, "Hello, World!");
|
||||
|
||||
let res = app
|
||||
.ready()
|
||||
.await
|
||||
.unwrap()
|
||||
.call(
|
||||
Request::builder()
|
||||
.method(Method::GET)
|
||||
.uri("/users?page=1&per_page=30")
|
||||
.body(Body::empty())
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(res.status(), StatusCode::OK);
|
||||
assert_eq!(body_to_string(res).await, "users#index");
|
||||
|
||||
let res = app
|
||||
.ready()
|
||||
.await
|
||||
.unwrap()
|
||||
.call(
|
||||
Request::builder()
|
||||
.method(Method::GET)
|
||||
.uri("/users")
|
||||
.body(Body::empty())
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(res.status(), StatusCode::BAD_REQUEST);
|
||||
assert_eq!(body_to_string(res).await, "");
|
||||
|
||||
let res = app
|
||||
.ready()
|
||||
.await
|
||||
.unwrap()
|
||||
.call(
|
||||
Request::builder()
|
||||
.method(Method::POST)
|
||||
.uri("/users")
|
||||
.body(Body::from(r#"{ "username": "bob" }"#))
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(res.status(), StatusCode::OK);
|
||||
assert_eq!(body_to_string(res).await, r#"{"username":"bob"}"#);
|
||||
}
|
||||
|
||||
async fn body_to_string<B>(res: Response<B>) -> String
|
||||
where
|
||||
B: http_body::Body,
|
||||
B::Error: fmt::Debug,
|
||||
{
|
||||
let bytes = hyper::body::to_bytes(res.into_body()).await.unwrap();
|
||||
String::from_utf8(bytes.to_vec()).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user