Crate kantan

source ·
Expand description

Kantan is a library for writing responses to servers.

  • You can spin up a Server within a test.
  • Create requests that will run against that.
  • Retrieve what they happen to return.
  • Assert that the response works how you expect.

It icludes built in suppot with Serde, Cookies, and other common crates for working with the web.

Getting Started

In essence; create your Axum application, create a Server, and then make requests against it.

use ::axum::Router;
use ::axum::extract::Json;
use ::axum::routing::put;
use ::axum_test::Server;
use ::serde_json::json;
use ::serde_json::Value;

async fn put_user(Json(user): Json<Value>) -> () {
    // todo
}

let my_app = Router::new()
    .route("/users", put(put_user))
    .into_make_service();

let server = Server::new(my_app)
    .unwrap();

let response = server.put("/users")
    .json(&json!({
        "username": "Terrance Pencilworth",
    }))
    .await;

Features

When you build a Server, you can turn on a feature to automatically save cookies across requests. This is used for automatically saving things like session cookies.

use ::axum::Router;
use ::axum_test::Server;
use ::axum_test::ServerConfig;

let my_app = Router::new()
    .into_make_service();

let config = ServerConfig {
    save_cookies: true,
    ..ServerConfig::default()
};
let server = Server::new_with_config(my_app, config)
    .unwrap();

Then when you make a request, any cookies that are returned will be reused by the next request. This is on a per server basis (it doesn’t save across servers).

You can turn this on or off per request, using `Request::do_save_cookies’ and Request::do_not_save_cookies’.

Content Type 📇

When performing a request, it will start with no content type at all.

You can set a default type for all Request objects to use, by setting the default_content_type in the ServerConfig. When creating the Server instance, using new_with_config.

use ::axum::Router;
use ::axum_test::Server;
use ::axum_test::ServerConfig;

let my_app = Router::new()
    .into_make_service();

let config = ServerConfig {
    default_content_type: Some("application/json".to_string()),
    ..ServerConfig::default()
};

let server = Server::new_with_config(my_app, config)
    .unwrap();

If there is no default, then a Request will try to guess the content type. Such as setting application/json when calling Request::json, and text/plain when calling Request::text. This will never override any default content type provided.

Finally on each Request, one can set the content type to use. By calling Request::content_type on it.

use ::axum::Router;
use ::axum::extract::Json;
use ::axum::routing::put;
use ::kantan::Server;
use ::serde_json::json;
use ::serde_json::Value;

async fn put_user(Json(user): Json<Value>) -> () {
    // todo
}

let my_app = Router::new()
    .route("/users", put(put_user))
    .into_make_service();

let server = Server::new(my_app)
    .unwrap();

let response = server.put("/users")
    .content_type(&"application/json")
    .json(&json!({
        "username": "Terrance Pencilworth",
    }))
    .await;

Fail Fast

This library is written to panic quickly. For example by default a response will presume to succeed and will panic if they don’t (which you can change). Functions to retreive cookies and headers will by default panic if they aren’t found.

This behaviour is unorthodox for Rust, however it is intentional to aid with writing tests. Where you want the test to fail as quickly, and skip on writing error handling code.

Re-exports

  • pub use ::hyper::http;

Structs

  • A Request represents a HTTP request to the test server.
  • The Server represents your application, running as a web server, and you can make web requests to your application.
  • The TestResponse represents the result of a Request. It is returned when you call await on a Request object.