Skip to main content
Axum applications are easy to test because Router implements tower::Service, allowing you to call handlers directly without spawning an HTTP server.

Basic testing approach

Create a function that returns your app for easy testing:
Separating your app construction into a function makes it reusable in both production code and tests.

Testing handlers with oneshot

Use oneshot to call your app with a single request:
1

Create the app

Call your app construction function to get a Router.
2

Build a request

Use Request::builder() or convenience methods like Request::get() to create requests.
3

Call with oneshot

Use tower::ServiceExt::oneshot() to send the request and get the response.
4

Assert the response

Check status codes, headers, and body contents.

Testing JSON endpoints

Test endpoints that accept and return JSON:

Testing with shared state

Test handlers that use State:

Testing ConnectInfo

Some extractors like ConnectInfo need special handling in tests:

Multiple requests with ready and call

For testing multiple requests, use ready() and call():
Call ready() before each call() to ensure the service is ready to handle the request.

Testing error cases

Test that your handlers properly reject invalid inputs:

Integration tests with a real server

Sometimes you need to test with an actual HTTP server:

Testing middleware

Test that middleware is properly applied:

Helper utilities

Create test helpers to reduce boilerplate:

Complete test example

Remember to add test dependencies in your Cargo.toml: tower = { version = "0.4", features = ["util"] } and http-body-util = "0.1".
Use cargo test to run all tests, or cargo test test_name to run a specific test.