Testing
All your testing, so far, has been manual: you've been launching the application and issuing requests to it with curl.
Let's move away from that: it's time to write some automated tests!
Black-box testing
The preferred way to test a Pavex application is to treat it as a black box: you should only test the application through its HTTP interface. This is the most realistic way to test your application: it's how your users will interact with it, after all.
The template project includes a reference example for the /api/ping endpoint:
use crate::helpers::TestApi; // (1)!
use pavex::http::StatusCode;
#[tokio::test]
async fn ping_works() {
let api = TestApi::spawn().await; // (2)!
let response = api.get_ping().await; // (3)!
assert_eq!(response.status(), StatusCode::OK);
}
TestApiis a helper struct that provides a convenient interface to interact with the application. It's defined inserver/tests/helpers.rs.TestApi::spawnstarts a new instance of the application in the background.TestApi::get_pingissues an actualGET /api/pingrequest to the application.
Add a new integration test
Let's write a new integration test to verify the behaviour on the happy path for GET /api/greet/{name}:
use pavex::http::StatusCode;
use crate::helpers::TestApi;
#[tokio::test]
async fn greet_happy_path() {
let api = TestApi::spawn().await;
let name = "Ursula";
let response = api
.api_client
.get(&format!("{}/api/greet/{name}", &api.api_address))
.header("User-Agent", "Test runner")
.send()
.await
.expect("Failed to execute request.");
assert_eq!(response.status(), StatusCode::OK);
assert_eq!(response.text().await.unwrap(), "Hello, Ursula!");
}
It follows the same pattern as the ping test: it spawns a new instance of the application, issues a request to it
and verifies that the response is correct.
Let's complement it with a test for the unhappy path as well: requests with a malformed User-Agent header should be
rejected.
// [...]
#[tokio::test]
async fn non_utf8_user_agent_is_rejected() {
let api = TestApi::spawn().await;
let name = "Ursula";
let response = api
.api_client
.get(&format!("{}/api/greet/{name}", &api.api_address))
.header("User-Agent", b"hello\xfa".as_slice())
.send()
.await
.expect("Failed to execute request.");
assert_eq!(response.status(), StatusCode::BAD_REQUEST);
assert_eq!(
response.text().await.unwrap(),
"The `User-Agent` header value can only use ASCII printable characters."
);
}
cargo px test should report three passing tests now. As a bonus exercise, try to add a test for the case where the
User-Agent header is missing.