测试 #
测试是保证应用质量的重要手段。本节将介绍如何测试Rocket应用。
单元测试 #
测试模块 #
rust
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_hash_password() {
let password = "test123";
let hash = hash_password(password).unwrap();
assert!(verify_password(password, &hash));
}
#[test]
fn test_invalid_password() {
let hash = hash_password("correct").unwrap();
assert!(!verify_password("wrong", &hash));
}
}
运行测试 #
bash
cargo test
集成测试 #
测试目录结构 #
text
tests/
├── common/
│ ├── mod.rs
│ └── fixtures.rs
├── user_test.rs
└── auth_test.rs
测试客户端 #
rust
use rocket::local::asynchronous::Client;
use rocket::local::blocking::Client as BlockingClient;
#[rocket::async_test]
async fn test_get_user() {
let client = Client::tracked(rocket())
.await
.expect("valid rocket instance");
let response = client.get("/api/users/1")
.dispatch()
.await;
assert_eq!(response.status(), rocket::http::Status::Ok);
}
阻塞客户端测试 #
rust
use rocket::local::blocking::Client;
#[test]
fn test_index() {
let client = Client::tracked(rocket()).expect("valid rocket instance");
let response = client.get("/").dispatch();
assert_eq!(response.status(), rocket::http::Status::Ok);
assert!(response.into_string().unwrap().contains("Hello"));
}
API测试 #
测试JSON响应 #
rust
use rocket::local::blocking::Client;
use rocket::serde::json::serde_json;
#[test]
fn test_json_response() {
let client = Client::tracked(rocket()).unwrap();
let response = client.get("/api/users/1").dispatch();
assert_eq!(response.status(), rocket::http::Status::Ok);
let body = response.into_string().unwrap();
let user: User = serde_json::from_str(&body).unwrap();
assert_eq!(user.id, 1);
}
测试POST请求 #
rust
#[test]
fn test_create_user() {
let client = Client::tracked(rocket()).unwrap();
let new_user = NewUser {
username: "test".to_string(),
email: "test@example.com".to_string(),
};
let response = client.post("/api/users")
.header(rocket::http::ContentType::JSON)
.body(serde_json::to_string(&new_user).unwrap())
.dispatch();
assert_eq!(response.status(), rocket::http::Status::Created);
}
测试认证 #
rust
#[test]
fn test_protected_route() {
let client = Client::tracked(rocket()).unwrap();
let response = client.get("/api/profile")
.header(rocket::http::Header::new("Authorization", "Bearer invalid-token"))
.dispatch();
assert_eq!(response.status(), rocket::http::Status::Unauthorized);
let response = client.get("/api/profile")
.header(rocket::http::Header::new("Authorization", "Bearer valid-token"))
.dispatch();
assert_eq!(response.status(), rocket::http::Status::Ok);
}
测试工具函数 #
创建测试Rocket实例 #
rust
fn test_rocket() -> Rocket<rocket::Build> {
rocket::build()
.manage(create_test_db())
.mount("/api", routes![get_user, create_user])
}
fn create_test_db() -> Db {
Db::new()
}
测试夹具 #
rust
mod fixtures {
use super::*;
pub fn create_test_user(db: &Db) -> User {
db.create_user(NewUser {
username: "test".to_string(),
email: "test@example.com".to_string(),
})
}
}
#[test]
fn test_with_fixture() {
let db = create_test_db();
let user = fixtures::create_test_user(&db);
assert_eq!(user.username, "test");
}
完整测试示例 #
rust
#[macro_use] extern crate rocket;
use rocket::local::blocking::Client;
use rocket::serde::json::Json;
use rocket::serde::{Serialize, Deserialize};
use std::sync::Mutex;
use std::collections::HashMap;
use rocket::State;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
struct User {
id: u32,
name: String,
}
struct Db {
users: Mutex<HashMap<u32, User>>,
}
impl Db {
fn new() -> Self {
Self {
users: Mutex::new(HashMap::new()),
}
}
fn get(&self, id: u32) -> Option<User> {
self.users.lock().unwrap().get(&id).cloned()
}
fn create(&self, name: String) -> User {
let mut users = self.users.lock().unwrap();
let id = users.len() as u32 + 1;
let user = User { id, name };
users.insert(id, user.clone());
user
}
}
#[get("/users/<id>")]
fn get_user(id: u32, db: &State<Db>) -> Option<Json<User>> {
db.get(id).map(Json)
}
#[post("/users", format = "json", data = "<user>")]
fn create_user(user: Json<serde_json::Value>, db: &State<Db>) -> Json<User> {
let name = user["name"].as_str().unwrap_or("Unknown").to_string();
Json(db.create(name))
}
fn test_rocket() -> rocket::Rocket<rocket::Build> {
rocket::build()
.manage(Db::new())
.mount("/api", routes![get_user, create_user])
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_get_nonexistent_user() {
let client = Client::tracked(test_rocket()).unwrap();
let response = client.get("/api/users/999").dispatch();
assert_eq!(response.status(), rocket::http::Status::NotFound);
}
#[test]
fn test_create_and_get_user() {
let client = Client::tracked(test_rocket()).unwrap();
let response = client.post("/api/users")
.header(rocket::http::ContentType::JSON)
.body(r#"{"name":"Alice"}"#)
.dispatch();
assert_eq!(response.status(), rocket::http::Status::Ok);
let body = response.into_string().unwrap();
let user: User = serde_json::from_str(&body).unwrap();
assert_eq!(user.name, "Alice");
let response = client.get(format!("/api/users/{}", user.id))
.dispatch();
assert_eq!(response.status(), rocket::http::Status::Ok);
}
}
#[launch]
fn rocket() -> _ {
rocket::build()
.manage(Db::new())
.mount("/api", routes![get_user, create_user])
}
下一步 #
掌握了测试后,让我们继续学习 性能优化,了解如何优化Rocket应用性能。
最后更新:2026-03-28