pub struct TestServer { /* private fields */ }
Expand description
The TestServer
runs your Axum application,
allowing you to make HTTP requests against it.
§Building
A TestServer
can be used to run an axum::Router
, an ::axum::routing::IntoMakeService
,
a shuttle_axum::ShuttleAxum
, and others.
The most straight forward approach is to call crate::TestServer::new
,
and pass in your application:
use axum::Router;
use axum::routing::get;
use axum_test::TestServer;
let app = Router::new()
.route(&"/hello", get(|| async { "hello!" }));
let server = TestServer::new(app)?;
§Requests
Requests are built by calling TestServer::get()
,
TestServer::post()
, TestServer::put()
,
TestServer::delete()
, and TestServer::patch()
methods.
Each returns a TestRequest
, which allows for customising the request content.
For example:
use axum::Router;
use axum::routing::get;
use axum_test::TestServer;
let app = Router::new()
.route(&"/hello", get(|| async { "hello!" }));
let server = TestServer::new(app)?;
let response = server.get(&"/hello")
.authorization_bearer("password12345")
.add_header("x-custom-header", "custom-value")
.await;
response.assert_text("hello!");
Request methods also exist for using Axum Extra axum_extra::routing::TypedPath
,
or for building Reqwest reqwest::RequestBuilder
. See those methods for detauls.
§Customising
A TestServer
can be built from a builder, by calling crate::TestServer::builder
,
and customising settings. This allows one to set mocked (default when possible)
or real http networking for your service.
use axum::Router;
use axum::routing::get;
use axum_test::TestServer;
let app = Router::new()
.route(&"/hello", get(|| async { "hello!" }));
// Customise server when building
let mut server = TestServer::builder()
.http_transport()
.expect_success_by_default()
.save_cookies()
.build(app)?;
// Add items to be sent on _all_ all requests
server.add_header("x-custom-for-all", "common-value");
let response = server.get("/hello").await;
Implementations§
Source§impl TestServer
impl TestServer
Sourcepub fn builder() -> TestServerBuilder
pub fn builder() -> TestServerBuilder
A helper function to create a builder for creating a TestServer
.
Sourcepub fn new<A>(app: A) -> Result<Self>where
A: IntoTransportLayer,
pub fn new<A>(app: A) -> Result<Self>where
A: IntoTransportLayer,
This will run the given Axum app, allowing you to make requests against it.
This is the same as creating a new TestServer
with a configuration,
and passing crate::TestServerConfig::default()
.
use axum::Router;
use axum::routing::get;
use axum_test::TestServer;
let app = Router::new()
.route(&"/hello", get(|| async { "hello!" }));
let server = TestServer::new(app)?;
The of applications that can be passed in include:
Sourcepub fn new_with_config<A, C>(app: A, config: C) -> Result<Self>
pub fn new_with_config<A, C>(app: A, config: C) -> Result<Self>
Similar to TestServer::new()
, with a customised configuration.
This includes type of transport in use (i.e. specify a specific port),
or change default settings (like the default content type for requests).
This can take a crate::TestServerConfig
or a crate::TestServerBuilder
.
See those for more information on configuration settings.
Sourcepub fn get(&self, path: &str) -> TestRequest
pub fn get(&self, path: &str) -> TestRequest
Creates a HTTP GET request to the path.
Sourcepub fn post(&self, path: &str) -> TestRequest
pub fn post(&self, path: &str) -> TestRequest
Creates a HTTP POST request to the given path.
Sourcepub fn patch(&self, path: &str) -> TestRequest
pub fn patch(&self, path: &str) -> TestRequest
Creates a HTTP PATCH request to the path.
Sourcepub fn put(&self, path: &str) -> TestRequest
pub fn put(&self, path: &str) -> TestRequest
Creates a HTTP PUT request to the path.
Sourcepub fn delete(&self, path: &str) -> TestRequest
pub fn delete(&self, path: &str) -> TestRequest
Creates a HTTP DELETE request to the path.
Sourcepub fn method(&self, method: Method, path: &str) -> TestRequest
pub fn method(&self, method: Method, path: &str) -> TestRequest
Creates a HTTP request, to the method and path provided.
pub fn reqwest_get(&self, path: &str) -> RequestBuilder
reqwest
only.pub fn reqwest_post(&self, path: &str) -> RequestBuilder
reqwest
only.pub fn reqwest_put(&self, path: &str) -> RequestBuilder
reqwest
only.pub fn reqwest_patch(&self, path: &str) -> RequestBuilder
reqwest
only.pub fn reqwest_delete(&self, path: &str) -> RequestBuilder
reqwest
only.pub fn reqwest_head(&self, path: &str) -> RequestBuilder
reqwest
only.Sourcepub fn reqwest_method(&self, method: Method, path: &str) -> RequestBuilder
Available on crate feature reqwest
only.
pub fn reqwest_method(&self, method: Method, path: &str) -> RequestBuilder
reqwest
only.Creates a HTTP request, using Reqwest, using the method + path described.
This expects a relative url to the TestServer
.
use axum::Router;
use axum_test::TestServer;
let my_app = Router::new();
let server = TestServer::builder()
.http_transport() // Important, must be HTTP!
.build(my_app)?;
// Build your request
let request = server.get(&"/user")
.add_header("x-custom-header", "example.com")
.content_type("application/yaml");
// await request to execute
let response = request.await;
Sourcepub fn get_websocket(&self, path: &str) -> TestRequest
Available on crate feature ws
only.
pub fn get_websocket(&self, path: &str) -> TestRequest
ws
only.Creates a request to the server, to start a Websocket connection, on the path given.
This is the requivalent of making a GET request to the endpoint, and setting the various headers needed for making an upgrade request.
Note, this requires the server to be running on a real HTTP
port. Either using a randomly assigned port, or a specified one.
See the TestServerConfig::transport
for more details.
§Example
use axum::Router;
use axum_test::TestServer;
let app = Router::new();
let server = TestServer::builder()
.http_transport()
.build(app)?;
let mut websocket = server
.get_websocket(&"/my-web-socket-end-point")
.await
.into_websocket()
.await;
websocket.send_text("Hello!").await;
Sourcepub fn typed_get<P>(&self, path: &P) -> TestRequestwhere
P: TypedPath,
Available on crate feature typed-routing
only.
pub fn typed_get<P>(&self, path: &P) -> TestRequestwhere
P: TypedPath,
typed-routing
only.Creates a HTTP GET request, using the typed path provided.
See axum-extra
for full documentation on TypedPath
.
§Example Test
Using a TypedPath
you can write build and test a route like below:
use axum::Json;
use axum::Router;
use axum::routing::get;
use axum_extra::routing::RouterExt;
use axum_extra::routing::TypedPath;
use serde::Deserialize;
use serde::Serialize;
use axum_test::TestServer;
#[derive(TypedPath, Deserialize)]
#[typed_path("/users/:user_id")]
struct UserPath {
pub user_id: u32,
}
// Build a typed route:
async fn route_get_user(UserPath { user_id }: UserPath) -> String {
format!("hello user {user_id}")
}
let app = Router::new()
.typed_get(route_get_user);
// Then test the route:
let server = TestServer::new(app)?;
server
.typed_get(&UserPath { user_id: 123 })
.await
.assert_text("hello user 123");
Sourcepub fn typed_post<P>(&self, path: &P) -> TestRequestwhere
P: TypedPath,
Available on crate feature typed-routing
only.
pub fn typed_post<P>(&self, path: &P) -> TestRequestwhere
P: TypedPath,
typed-routing
only.Creates a HTTP POST request, using the typed path provided.
See axum-extra
for full documentation on TypedPath
.
Sourcepub fn typed_patch<P>(&self, path: &P) -> TestRequestwhere
P: TypedPath,
Available on crate feature typed-routing
only.
pub fn typed_patch<P>(&self, path: &P) -> TestRequestwhere
P: TypedPath,
typed-routing
only.Creates a HTTP PATCH request, using the typed path provided.
See axum-extra
for full documentation on TypedPath
.
Sourcepub fn typed_put<P>(&self, path: &P) -> TestRequestwhere
P: TypedPath,
Available on crate feature typed-routing
only.
pub fn typed_put<P>(&self, path: &P) -> TestRequestwhere
P: TypedPath,
typed-routing
only.Creates a HTTP PUT request, using the typed path provided.
See axum-extra
for full documentation on TypedPath
.
Sourcepub fn typed_delete<P>(&self, path: &P) -> TestRequestwhere
P: TypedPath,
Available on crate feature typed-routing
only.
pub fn typed_delete<P>(&self, path: &P) -> TestRequestwhere
P: TypedPath,
typed-routing
only.Creates a HTTP DELETE request, using the typed path provided.
See axum-extra
for full documentation on TypedPath
.
Sourcepub fn typed_method<P>(&self, method: Method, path: &P) -> TestRequestwhere
P: TypedPath,
Available on crate feature typed-routing
only.
pub fn typed_method<P>(&self, method: Method, path: &P) -> TestRequestwhere
P: TypedPath,
typed-routing
only.Creates a typed HTTP request, using the method provided.
See axum-extra
for full documentation on TypedPath
.
Sourcepub fn server_address(&self) -> Option<Url>
pub fn server_address(&self) -> Option<Url>
Returns the local web address for the test server, if an address is available.
The address is available when running as a real web server,
by setting the TestServerConfig
transport
field to Transport::HttpRandomPort
or Transport::HttpIpPort
.
This will return None
when there is mock HTTP transport (the default).
Sourcepub fn server_url(&self, path: &str) -> Result<Url>
pub fn server_url(&self, path: &str) -> Result<Url>
This turns a relative path, into an absolute path to the server.
i.e. A path like /users/123
will become something like http://127.0.0.1:1234/users/123
.
The absolute address can be used to make requests to the running server, using any appropriate client you wish.
§Example
use axum::Router;
use axum_test::TestServer;
let app = Router::new();
let server = TestServer::builder()
.http_transport()
.build(app)?;
let full_url = server.server_url(&"/users/123?filter=enabled")?;
// Prints something like ... http://127.0.0.1:1234/users/123?filter=enabled
println!("{full_url}");
This will return an error if you are using the mock transport.
Real HTTP transport is required to use this method (see TestServerConfig
transport
field).
It will also return an error if you provide an absolute path,
for example if you pass in http://google.com
.
Adds a single cookie to be included on all future requests.
If a cookie with the same name already exists, then it will be replaced.
Adds extra cookies to be used on all future requests.
Any cookies which have the same name as the new cookies, will get replaced.
Clears all of the cookies stored internally.
Requests made using this TestServer
will save their cookies for future requests to send.
This behaviour is off by default.
Requests made using this TestServer
will not save their cookies for future requests to send up.
This is the default behaviour.
Sourcepub fn expect_success(&mut self)
pub fn expect_success(&mut self)
Requests made using this TestServer
will assert a HTTP status in the 2xx range will be returned, unless marked otherwise.
By default this behaviour is off.
Sourcepub fn expect_failure(&mut self)
pub fn expect_failure(&mut self)
Requests made using this TestServer
will assert a HTTP status is outside the 2xx range will be returned, unless marked otherwise.
By default this behaviour is off.
Sourcepub fn add_query_param<V>(&mut self, key: &str, value: V)where
V: Serialize,
pub fn add_query_param<V>(&mut self, key: &str, value: V)where
V: Serialize,
Adds a query parameter to be sent on all future requests.
Sourcepub fn add_query_params<V>(&mut self, query_params: V)where
V: Serialize,
pub fn add_query_params<V>(&mut self, query_params: V)where
V: Serialize,
Adds query parameters to be sent on all future requests.
Sourcepub fn add_raw_query_param(&mut self, raw_query_param: &str)
pub fn add_raw_query_param(&mut self, raw_query_param: &str)
Adds a raw query param, with no urlencoding of any kind, to be send on all future requests.
Sourcepub fn clear_query_params(&mut self)
pub fn clear_query_params(&mut self)
Clears all query params set.
Sourcepub fn add_header<N, V>(&mut self, name: N, value: V)
pub fn add_header<N, V>(&mut self, name: N, value: V)
Adds a header to be sent with all future requests built from this TestServer
.
use axum::Router;
use axum_test::TestServer;
let app = Router::new();
let mut server = TestServer::new(app)?;
server.add_header("x-custom-header", "custom-value");
server.add_header(http::header::CONTENT_LENGTH, 12345);
server.add_header(http::header::HOST, "example.com");
let response = server.get(&"/my-end-point")
.await;
Sourcepub fn clear_headers(&mut self)
pub fn clear_headers(&mut self)
Clears all headers set so far.
Sourcepub fn scheme(&mut self, scheme: &str)
pub fn scheme(&mut self, scheme: &str)
Sets the scheme to use when making all requests from the TestServer
.
i.e. http or https.
The default scheme is ‘http’.
use axum::Router;
use axum_test::TestServer;
let app = Router::new();
let mut server = TestServer::new(app)?;
server
.scheme(&"https");
let response = server
.get(&"/my-end-point")
.await;
Sourcepub fn is_running(&self) -> bool
pub fn is_running(&self) -> bool
Returns true or false if the underlying service inside the TestServer
is still running. For many types of services this will always return true
.
When a TestServer
is built using axum::serve::WithGracefulShutdown
,
this will return false if the service has shutdown.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for TestServer
impl !RefUnwindSafe for TestServer
impl Send for TestServer
impl Sync for TestServer
impl Unpin for TestServer
impl !UnwindSafe for TestServer
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> FutureExt for T
impl<T> FutureExt for T
Source§fn with_context(self, otel_cx: Context) -> WithContext<Self>
fn with_context(self, otel_cx: Context) -> WithContext<Self>
Source§fn with_current_context(self) -> WithContext<Self>
fn with_current_context(self) -> WithContext<Self>
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T
in a tonic::Request
Source§impl<T> Paint for Twhere
T: ?Sized,
impl<T> Paint for Twhere
T: ?Sized,
Source§fn fg(&self, value: Color) -> Painted<&T>
fn fg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self
with the foreground set to
value
.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like red()
and
green()
, which have the same functionality but are
pithier.
§Example
Set foreground color to white using fg()
:
use yansi::{Paint, Color};
painted.fg(Color::White);
Set foreground color to white using white()
.
use yansi::Paint;
painted.white();
Source§fn bright_black(&self) -> Painted<&T>
fn bright_black(&self) -> Painted<&T>
Returns self
with the
fg()
set to
Color::BrightBlack
.
§Example
println!("{}", value.bright_black());
Source§fn bright_red(&self) -> Painted<&T>
fn bright_red(&self) -> Painted<&T>
Source§fn bright_green(&self) -> Painted<&T>
fn bright_green(&self) -> Painted<&T>
Returns self
with the
fg()
set to
Color::BrightGreen
.
§Example
println!("{}", value.bright_green());
Source§fn bright_yellow(&self) -> Painted<&T>
fn bright_yellow(&self) -> Painted<&T>
Returns self
with the
fg()
set to
Color::BrightYellow
.
§Example
println!("{}", value.bright_yellow());
Source§fn bright_blue(&self) -> Painted<&T>
fn bright_blue(&self) -> Painted<&T>
Source§fn bright_magenta(&self) -> Painted<&T>
fn bright_magenta(&self) -> Painted<&T>
Returns self
with the
fg()
set to
Color::BrightMagenta
.
§Example
println!("{}", value.bright_magenta());
Source§fn bright_cyan(&self) -> Painted<&T>
fn bright_cyan(&self) -> Painted<&T>
Source§fn bright_white(&self) -> Painted<&T>
fn bright_white(&self) -> Painted<&T>
Returns self
with the
fg()
set to
Color::BrightWhite
.
§Example
println!("{}", value.bright_white());
Source§fn bg(&self, value: Color) -> Painted<&T>
fn bg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self
with the background set to
value
.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like on_red()
and
on_green()
, which have the same functionality but
are pithier.
§Example
Set background color to red using fg()
:
use yansi::{Paint, Color};
painted.bg(Color::Red);
Set background color to red using on_red()
.
use yansi::Paint;
painted.on_red();
Source§fn on_primary(&self) -> Painted<&T>
fn on_primary(&self) -> Painted<&T>
Source§fn on_magenta(&self) -> Painted<&T>
fn on_magenta(&self) -> Painted<&T>
Source§fn on_bright_black(&self) -> Painted<&T>
fn on_bright_black(&self) -> Painted<&T>
Returns self
with the
bg()
set to
Color::BrightBlack
.
§Example
println!("{}", value.on_bright_black());
Source§fn on_bright_red(&self) -> Painted<&T>
fn on_bright_red(&self) -> Painted<&T>
Source§fn on_bright_green(&self) -> Painted<&T>
fn on_bright_green(&self) -> Painted<&T>
Returns self
with the
bg()
set to
Color::BrightGreen
.
§Example
println!("{}", value.on_bright_green());
Source§fn on_bright_yellow(&self) -> Painted<&T>
fn on_bright_yellow(&self) -> Painted<&T>
Returns self
with the
bg()
set to
Color::BrightYellow
.
§Example
println!("{}", value.on_bright_yellow());
Source§fn on_bright_blue(&self) -> Painted<&T>
fn on_bright_blue(&self) -> Painted<&T>
Returns self
with the
bg()
set to
Color::BrightBlue
.
§Example
println!("{}", value.on_bright_blue());
Source§fn on_bright_magenta(&self) -> Painted<&T>
fn on_bright_magenta(&self) -> Painted<&T>
Returns self
with the
bg()
set to
Color::BrightMagenta
.
§Example
println!("{}", value.on_bright_magenta());
Source§fn on_bright_cyan(&self) -> Painted<&T>
fn on_bright_cyan(&self) -> Painted<&T>
Returns self
with the
bg()
set to
Color::BrightCyan
.
§Example
println!("{}", value.on_bright_cyan());
Source§fn on_bright_white(&self) -> Painted<&T>
fn on_bright_white(&self) -> Painted<&T>
Returns self
with the
bg()
set to
Color::BrightWhite
.
§Example
println!("{}", value.on_bright_white());
Source§fn attr(&self, value: Attribute) -> Painted<&T>
fn attr(&self, value: Attribute) -> Painted<&T>
Enables the styling Attribute
value
.
This method should be used rarely. Instead, prefer to use
attribute-specific builder methods like bold()
and
underline()
, which have the same functionality
but are pithier.
§Example
Make text bold using attr()
:
use yansi::{Paint, Attribute};
painted.attr(Attribute::Bold);
Make text bold using using bold()
.
use yansi::Paint;
painted.bold();
Source§fn underline(&self) -> Painted<&T>
fn underline(&self) -> Painted<&T>
Returns self
with the
attr()
set to
Attribute::Underline
.
§Example
println!("{}", value.underline());
Source§fn rapid_blink(&self) -> Painted<&T>
fn rapid_blink(&self) -> Painted<&T>
Returns self
with the
attr()
set to
Attribute::RapidBlink
.
§Example
println!("{}", value.rapid_blink());
Source§fn quirk(&self, value: Quirk) -> Painted<&T>
fn quirk(&self, value: Quirk) -> Painted<&T>
Enables the yansi
Quirk
value
.
This method should be used rarely. Instead, prefer to use quirk-specific
builder methods like mask()
and
wrap()
, which have the same functionality but are
pithier.
§Example
Enable wrapping using .quirk()
:
use yansi::{Paint, Quirk};
painted.quirk(Quirk::Wrap);
Enable wrapping using wrap()
.
use yansi::Paint;
painted.wrap();
Source§fn clear(&self) -> Painted<&T>
👎Deprecated since 1.0.1: renamed to resetting()
due to conflicts with Vec::clear()
.
The clear()
method will be removed in a future release.
fn clear(&self) -> Painted<&T>
resetting()
due to conflicts with Vec::clear()
.
The clear()
method will be removed in a future release.Source§fn whenever(&self, value: Condition) -> Painted<&T>
fn whenever(&self, value: Condition) -> Painted<&T>
Conditionally enable styling based on whether the Condition
value
applies. Replaces any previous condition.
See the crate level docs for more details.
§Example
Enable styling painted
only when both stdout
and stderr
are TTYs:
use yansi::{Paint, Condition};
painted.red().on_yellow().whenever(Condition::STDOUTERR_ARE_TTY);