06
测试与 API 文档
Tests, Mock, Proptest, OpenAPI
Rust 把测试当一等公民——cargo test 一条命令跑全部,文档注释里的代码块自动当测试跑。这一章讲单元测试、异步测试、Mock、属性测试和自动生成 OpenAPI 文档。
单元测试与异步测试
// src/lib.rs 末尾
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_add() {
assert_eq!(2 + 2, 4);
assert!(true);
}
// 异步测试:用 tokio::test
#[tokio::test]
async fn test_fetch() {
let r = fetch_user(1).await;
assert_eq!(r.name, "tom");
}
#[test]
#[should_panic(expected = "除以零")]
fn test_div_zero() { div(1, 0); }
}
$ cargo test
running 3 tests
test tests::test_add ... ok
test tests::test_fetch ... ok
test tests::test_div_zero ... ok
集成测试与文档测试
集成测试放在项目根目录的 tests/ 文件夹,每个文件都是独立的 crate,能调你 lib crate 的公开 API。文档测试更爽——你在 /// 注释里写的代码块,cargo test 会真的编译执行,保证文档永远不过时。
Mock 与属性测试
// mockall:给 trait 生成 Mock 实现
use mockall::{mock, predicate::*};
#[automock]
trait UserRepo {
async fn find(&self, id: u64) -> Option<User>;
}
#[tokio::test]
async fn test_service() {
let mut mock = MockUserRepo::new();
mock.expect_find()
.with(eq(1))
.returning(|_| Some(User { id: 1, ..Default::default() }));
// ... 用 mock 测 service
}
proptest 做属性测试:你写"对任意输入,结果必须满足某个性质",它自动生成几百个随机输入帮你压。比如"任意 Vec,反转两次等于原 Vec"。
OpenAPI 文档:utoipa
Axum 配合 utoipa,给 handler 和结构体加 derive,自动生成 OpenAPI 3.0 spec,再用 swagger-ui 渲染成在线文档。比写 Swagger YAML 文件靠谱多了——因为它从你的真实代码生成。
use utoipa::{OpenApi, ToSchema};
use utoipa_swagger_ui::SwaggerUi;
#[derive(OpenApi)]
#[openapi(paths(create_user, get_user), components(schemas(User)))]
struct ApiDoc;
let app = Router::new()
.merge(SwaggerUi::new("/docs").url("/api.json", ApiDoc::openapi()));
记
本章小结
① #[cfg(test)] 单元测试、#[tokio::test] 异步测试、tests/ 集成测试、/// 文档测试。
② Mock 用 mockall,属性测试用 proptest,API 文档用 utoipa + swagger-ui。