Skip to content

Commit 28d8d9b

Browse files
authored
Refactor TestClient usage (#3121)
1 parent 3497e5d commit 28d8d9b

File tree

12 files changed

+68
-65
lines changed

12 files changed

+68
-65
lines changed

Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

axum-core/Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,9 @@ tower-http = { version = "0.6.0", optional = true, features = ["limit"] }
3535
tracing = { version = "0.1.37", default-features = false, optional = true }
3636

3737
[dev-dependencies]
38-
axum = { path = "../axum" }
38+
axum = { path = "../axum", features = ["__private"] }
3939
axum-extra = { path = "../axum-extra", features = ["typed-header"] }
40+
axum-macros = { path = "../axum-macros", features = ["__private"] }
4041
futures-util = { version = "0.3", default-features = false, features = ["alloc"] }
4142
hyper = "1.0.0"
4243
tokio = { version = "1.25.0", features = ["macros"] }

axum-core/src/extract/request_parts.rs

+25
Original file line numberDiff line numberDiff line change
@@ -166,3 +166,28 @@ where
166166
Ok(req.into_body())
167167
}
168168
}
169+
170+
#[cfg(test)]
171+
mod tests {
172+
use axum::{extract::Extension, routing::get, test_helpers::*, Router};
173+
use http::{Method, StatusCode};
174+
175+
#[crate::test]
176+
async fn extract_request_parts() {
177+
#[derive(Clone)]
178+
struct Ext;
179+
180+
async fn handler(parts: http::request::Parts) {
181+
assert_eq!(parts.method, Method::GET);
182+
assert_eq!(parts.uri, "/");
183+
assert_eq!(parts.version, http::Version::HTTP_11);
184+
assert_eq!(parts.headers["x-foo"], "123");
185+
parts.extensions.get::<Ext>().unwrap();
186+
}
187+
188+
let client = TestClient::new(Router::new().route("/", get(handler)).layer(Extension(Ext)));
189+
190+
let res = client.get("/").header("x-foo", "123").await;
191+
assert_eq!(res.status(), StatusCode::OK);
192+
}
193+
}

axum-core/src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,6 @@ pub mod response;
3131
pub type BoxError = Box<dyn std::error::Error + Send + Sync>;
3232

3333
pub use self::ext_traits::{request::RequestExt, request_parts::RequestPartsExt};
34+
35+
#[cfg(test)]
36+
use axum_macros::__private_axum_test as test;

axum-extra/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ tracing = { version = "0.1.37", default-features = false, optional = true }
7676
typed-json = { version = "0.1.1", optional = true }
7777

7878
[dev-dependencies]
79-
axum = { path = "../axum", features = ["macros"] }
79+
axum = { path = "../axum", features = ["macros", "__private"] }
8080
axum-macros = { path = "../axum-macros", features = ["__private"] }
8181
hyper = "1.0.0"
8282
reqwest = { version = "0.12", default-features = false, features = ["json", "stream", "multipart"] }

axum-extra/src/lib.rs

+1-13
Original file line numberDiff line numberDiff line change
@@ -80,16 +80,4 @@ pub mod __private {
8080
use axum_macros::__private_axum_test as test;
8181

8282
#[cfg(test)]
83-
#[allow(unused_imports)]
84-
pub(crate) mod test_helpers {
85-
use axum::{extract::Request, response::Response, serve};
86-
87-
mod test_client {
88-
#![allow(dead_code)]
89-
include!(concat!(
90-
env!("CARGO_MANIFEST_DIR"),
91-
"/../axum/src/test_helpers/test_client.rs"
92-
));
93-
}
94-
pub(crate) use self::test_client::*;
95-
}
83+
pub(crate) use axum::test_helpers;

axum/Cargo.toml

+8
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ __private_docs = [
4545
"tower/full", "dep:tower-http",
4646
]
4747

48+
# This feature is used to enable private test helper usage
49+
# in `axum-core` and `axum-extra`.
50+
__private = ["tokio", "http1", "dep:reqwest"]
51+
4852
[dependencies]
4953
axum-core = { path = "../axum-core", version = "0.5.0-rc.1" }
5054
bytes = "1.0"
@@ -72,6 +76,7 @@ form_urlencoded = { version = "1.1.0", optional = true }
7276
hyper = { version = "1.1.0", optional = true }
7377
hyper-util = { version = "0.1.3", features = ["tokio", "server", "service"], optional = true }
7478
multer = { version = "3.0.0", optional = true }
79+
reqwest = { version = "0.12", optional = true, default-features = false, features = ["json", "stream", "multipart"] }
7580
serde_json = { version = "1.0", features = ["raw_value"], optional = true }
7681
serde_path_to_error = { version = "0.1.8", optional = true }
7782
serde_urlencoded = { version = "0.7", optional = true }
@@ -214,6 +219,9 @@ allowed = [
214219
"http_body",
215220
"serde",
216221
"tokio",
222+
223+
# for the `__private` feature
224+
"reqwest",
217225
]
218226

219227
[[bench]]

axum/src/extract/mod.rs

-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ pub(crate) mod nested_path;
1515
mod original_uri;
1616
mod raw_form;
1717
mod raw_query;
18-
mod request_parts;
1918
mod state;
2019

2120
#[doc(inline)]

axum/src/extract/request_parts.rs

-27
This file was deleted.

axum/src/lib.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -446,8 +446,9 @@ pub mod routing;
446446
#[cfg(all(feature = "tokio", any(feature = "http1", feature = "http2")))]
447447
pub mod serve;
448448

449-
#[cfg(test)]
450-
mod test_helpers;
449+
#[cfg(any(test, feature = "__private"))]
450+
#[allow(missing_docs, missing_debug_implementations, clippy::print_stdout)]
451+
pub mod test_helpers;
451452

452453
#[doc(no_inline)]
453454
pub use http;

axum/src/test_helpers/mod.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,17 @@
33
use crate::{extract::Request, response::Response, serve};
44

55
mod test_client;
6-
pub(crate) use self::test_client::*;
6+
pub use self::test_client::*;
77

8+
#[cfg(test)]
89
pub(crate) mod tracing_helpers;
910

11+
#[cfg(test)]
1012
pub(crate) mod counting_cloneable_state;
1113

14+
#[cfg(test)]
1215
pub(crate) fn assert_send<T: Send>() {}
16+
#[cfg(test)]
1317
pub(crate) fn assert_sync<T: Sync>() {}
1418

1519
#[allow(dead_code)]

axum/src/test_helpers/test_client.rs

+19-19
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,13 @@ where
2929
addr
3030
}
3131

32-
pub(crate) struct TestClient {
32+
pub struct TestClient {
3333
client: reqwest::Client,
3434
addr: SocketAddr,
3535
}
3636

3737
impl TestClient {
38-
pub(crate) fn new<S>(svc: S) -> Self
38+
pub fn new<S>(svc: S) -> Self
3939
where
4040
S: Service<Request, Response = Response, Error = Infallible> + Clone + Send + 'static,
4141
S::Future: Send,
@@ -50,63 +50,63 @@ impl TestClient {
5050
TestClient { client, addr }
5151
}
5252

53-
pub(crate) fn get(&self, url: &str) -> RequestBuilder {
53+
pub fn get(&self, url: &str) -> RequestBuilder {
5454
RequestBuilder {
5555
builder: self.client.get(format!("http://{}{url}", self.addr)),
5656
}
5757
}
5858

59-
pub(crate) fn head(&self, url: &str) -> RequestBuilder {
59+
pub fn head(&self, url: &str) -> RequestBuilder {
6060
RequestBuilder {
6161
builder: self.client.head(format!("http://{}{url}", self.addr)),
6262
}
6363
}
6464

65-
pub(crate) fn post(&self, url: &str) -> RequestBuilder {
65+
pub fn post(&self, url: &str) -> RequestBuilder {
6666
RequestBuilder {
6767
builder: self.client.post(format!("http://{}{url}", self.addr)),
6868
}
6969
}
7070

7171
#[allow(dead_code)]
72-
pub(crate) fn put(&self, url: &str) -> RequestBuilder {
72+
pub fn put(&self, url: &str) -> RequestBuilder {
7373
RequestBuilder {
7474
builder: self.client.put(format!("http://{}{url}", self.addr)),
7575
}
7676
}
7777

7878
#[allow(dead_code)]
79-
pub(crate) fn patch(&self, url: &str) -> RequestBuilder {
79+
pub fn patch(&self, url: &str) -> RequestBuilder {
8080
RequestBuilder {
8181
builder: self.client.patch(format!("http://{}{url}", self.addr)),
8282
}
8383
}
8484

8585
#[allow(dead_code)]
86-
pub(crate) fn server_port(&self) -> u16 {
86+
pub fn server_port(&self) -> u16 {
8787
self.addr.port()
8888
}
8989
}
9090

91-
pub(crate) struct RequestBuilder {
91+
pub struct RequestBuilder {
9292
builder: reqwest::RequestBuilder,
9393
}
9494

9595
impl RequestBuilder {
96-
pub(crate) fn body(mut self, body: impl Into<reqwest::Body>) -> Self {
96+
pub fn body(mut self, body: impl Into<reqwest::Body>) -> Self {
9797
self.builder = self.builder.body(body);
9898
self
9999
}
100100

101-
pub(crate) fn json<T>(mut self, json: &T) -> Self
101+
pub fn json<T>(mut self, json: &T) -> Self
102102
where
103103
T: serde::Serialize,
104104
{
105105
self.builder = self.builder.json(json);
106106
self
107107
}
108108

109-
pub(crate) fn header<K, V>(mut self, key: K, value: V) -> Self
109+
pub fn header<K, V>(mut self, key: K, value: V) -> Self
110110
where
111111
HeaderName: TryFrom<K>,
112112
<HeaderName as TryFrom<K>>::Error: Into<http::Error>,
@@ -118,7 +118,7 @@ impl RequestBuilder {
118118
}
119119

120120
#[allow(dead_code)]
121-
pub(crate) fn multipart(mut self, form: reqwest::multipart::Form) -> Self {
121+
pub fn multipart(mut self, form: reqwest::multipart::Form) -> Self {
122122
self.builder = self.builder.multipart(form);
123123
self
124124
}
@@ -138,7 +138,7 @@ impl IntoFuture for RequestBuilder {
138138
}
139139

140140
#[derive(Debug)]
141-
pub(crate) struct TestResponse {
141+
pub struct TestResponse {
142142
response: reqwest::Response,
143143
}
144144

@@ -152,27 +152,27 @@ impl Deref for TestResponse {
152152

153153
impl TestResponse {
154154
#[allow(dead_code)]
155-
pub(crate) async fn bytes(self) -> Bytes {
155+
pub async fn bytes(self) -> Bytes {
156156
self.response.bytes().await.unwrap()
157157
}
158158

159-
pub(crate) async fn text(self) -> String {
159+
pub async fn text(self) -> String {
160160
self.response.text().await.unwrap()
161161
}
162162

163163
#[allow(dead_code)]
164-
pub(crate) async fn json<T>(self) -> T
164+
pub async fn json<T>(self) -> T
165165
where
166166
T: serde::de::DeserializeOwned,
167167
{
168168
self.response.json().await.unwrap()
169169
}
170170

171-
pub(crate) async fn chunk(&mut self) -> Option<Bytes> {
171+
pub async fn chunk(&mut self) -> Option<Bytes> {
172172
self.response.chunk().await.unwrap()
173173
}
174174

175-
pub(crate) async fn chunk_text(&mut self) -> Option<String> {
175+
pub async fn chunk_text(&mut self) -> Option<String> {
176176
let chunk = self.chunk().await?;
177177
Some(String::from_utf8(chunk.to_vec()).unwrap())
178178
}

0 commit comments

Comments
 (0)