拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

setup teardown rust如何实现

setup teardown rust如何实现

Rust 里没有 JUnit 那种“全局 before/after”钩子,但setup/teardown 通常有三层做法:简单场景用Drop,测试上下文用test-context,复杂套件用rstestfixture 或suitest。

1. 最轻量:用Drop做 teardown

Rust 的Drop天然适合做清理:连接池、临时文件、测试目录、临时端口绑定都可以靠它回收。

struct TempDir { path: std::path::PathBuf, } impl TempDir { fn new() -> Self { let path = std::env::temp_dir().join("my_test"); std::fs::create_dir_all(&path).unwrap(); Self { path } } } impl Drop for TempDir { fn drop(&mut self) { let _ = std::fs::remove_dir_all(&self.path); } } #[test] fn test_with_temp_dir() { let dir = TempDir::new(); // 使用 dir.path 做测试 }

2. 最接近 JUnit:test-context

如果你想要明确的setup()/teardown(),test-context很合适,还能配合#[tokio::test]。

use test_context::{test_context, AsyncTestContext}; struct AppContext { db_url: String, } #[async_trait::async_trait] impl AsyncTestContext for AppContext { async fn setup() -> Self { Self { db_url: "postgres://localhost:5432/test".into(), } } async fn teardown(self) { // 清理测试数据库、关闭连接池等 } } #[test_context(AppContext)] #[tokio::test] async fn test_handler(ctx: &mut AppContext) { assert!(!ctx.db_url.is_empty()); }

3. 参数化 + fixture:rstest

rstest没有显式的beforeEach/afterEach,但可以用 fixture 做 setup,用Drop或#[once]控制生命周期。

use rstest::*; #[fixture] fn db_url() -> String { "postgres://localhost/test".into() } #[fixture] fn temp_dir() -> TempDir { TempDir::new() } #[rstest] fn test_query(db_url: String, temp_dir: TempDir) { assert!(!db_url.is_empty()); }

如果 fixture 需要全局共享,比如测试数据库连接池,可以用:

#[fixture] #[once] fn pool() -> Pool { Pool::new() }

4. 需要完整套件钩子:suitest/spectacular

如果你确实需要before_all / before_each / after_each / after_all,可以用suitest。

use suitest::{suite, before_all, after_all, before_each, after_each}; #[suite(my_suite)] mod tests { use suitest::*; #[before_all] async fn setup() -> usize { 42 } #[after_all] async fn teardown(value: usize) { assert_eq!(value, 42); } #[before_each] fn before() -> String { "ready".into() } #[after_each] fn after(state: String) { assert_eq!(state, "ready"); } #[test] fn it_works(state: String, value: usize) { assert_eq!(state, "ready"); assert_eq!(value, 42); } }

选型建议

场景推荐
临时文件、临时目录、简单资源清理Drop
每个测试需要统一上下文test-context
参数化测试 + fixture 注入rstest
需要 before/after 套件钩子suitest/spectacular
框架集成测试rstest+Drop+mockall

如果是在搭后端框架的测试基础设施,建议优先用rstest管理 fixture,Drop管 teardown,test-context补显式 setup/teardown。这样既能保持工程化边界清晰,也不会引入太重的测试 harness。

需要的话,我可以帮你把这套封装成框架里的TestApp和TestFixture基类。

返回列表