Study
Axum

Testing dengan tower::ServiceExt

Penjelasan

Karena `Router` di Axum sebenarnya adalah `Service` dari Tower, kamu bisa menguji handler tanpa membuka port jaringan sama sekali — cukup panggil router-nya langsung dengan sebuah `Request` buatan, memakai method `.oneshot(request)` dari trait `tower::ServiceExt`. Ini jauh lebih cepat dan stabil dibanding test end-to-end yang benar-benar membuka koneksi TCP. Alurnya: buat instance `Router` (bisa memanggil fungsi yang sama dengan yang dipakai di `main`), buat `Request` dengan `http::Request::builder()`, lalu panggil `app.oneshot(request).await`. Hasilnya adalah `Response` yang bisa kamu periksa status code-nya dan body-nya (dengan membaca body lalu mem-parsing JSON kalau perlu). Pola ini biasanya ditulis di dalam modul `#[cfg(test)]` pada file yang sama dengan router-mu, memakai `#[tokio::test]` sebagai pengganti `#[test]` biasa karena handler-nya async.

Contoh Konsep

use axum::{body::Body, http::{Request, StatusCode}, routing::get, Router};
use tower::ServiceExt; // untuk .oneshot()

async fn hello() -> &'static str {
    "Hello, Axum!"
}

fn app() -> Router {
    Router::new().route("/", get(hello))
}

#[tokio::main]
async fn main() {
    let listener = tokio::net::TcpListener::bind("127.0.0.1:3000").await.unwrap();
    axum::serve(listener, app()).await.unwrap();
}

#[cfg(test)]
mod tests {
    use super::*;

    #[tokio::test]
    async fn hello_mengembalikan_200() {
        let request = Request::builder().uri("/").body(Body::empty()).unwrap();
        let response = app().oneshot(request).await.unwrap();
        assert_eq!(response.status(), StatusCode::OK);
    }
}

Praktikum

Lengkapi test di bawah supaya memverifikasi handler `/notfound` (yang tidak didaftarkan) mengembalikan status 404.

Editor Latihan

Ketik/edit bebas di sini untuk latihan — kode ini tidak dijalankan.

Tips

Untuk memeriksa isi body JSON pada response test, pakai `axum::body::to_bytes(response.into_body(), usize::MAX).await.unwrap()` lalu `serde_json::from_slice(...)` untuk mem-parsingnya kembali menjadi struct — pola ini sering dibungkus jadi helper function kecil kalau kamu punya banyak test.