如何创建和删除用于测试的共享资源?

How to create and drop a shared resource for tests?

我的一部分测试需要一个只允许创建一次的资源。 此资源也必须在某个时候删除(而不是在需要它的最后一个测试完成之前)。

目前我使用静态 OnceCell:

struct MyResource {}

impl Drop for MyResource {
    fn drop(&mut self) {
        println!("Dropped MyResource");
    }
}

impl MyResource {
    fn new() -> MyResource {
        println!("Created MyResource");
        MyResource {}
    }
}

fn main() {
    let _my_resource = MyResource::new();
    println!("Hello, world!");
}

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

    static GET_RESOURCE: OnceCell<MyResource> = OnceCell::const_new();

    async fn init_my_resource() {
        GET_RESOURCE.get_or_init(|| async {
            MyResource::new()
        }).await;
    }

    #[tokio::test]
    async fn some_test() {
        init_my_resource().await;
        assert_eq!("some assert", "some assert");
    }
}

这工作正常,只是它从不丢弃资源。

是否有更好的方法来执行此操作,同时也会丢弃资源?

的答案没有回答这个问题,因为它只回答了如何初始化一些东西,但没有回答如何在测试后删除一些东西 运行。

crate ctor 提供了 dtor 宏,它允许您在完成所有测试后手动 drop 资源。

我找到的最多 straight-forward 的解决方案是由 crate static_init:

提供的
struct MyResource {}

impl Drop for MyResource {
    fn drop(&mut self) {
        println!("Dropped my rescource");
    }
}

impl MyResource {
    fn new() -> MyResource {
        println!("Created MyResource");
        MyResource {}
    }
}

fn main() {
    let _my_resource = MyResource::new();
    println!("Hello, world!");
}

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

    #[dynamic(drop)]
    static mut RES: MyResource = MyResource::new();

    #[tokio::test]
    async fn some_test() {
        println!("Running test");
        assert_eq!("some assert", "some assert");
    }
}

另一个建议的解决方案是使用 crate ctor 的 ctor 和 dtor。虽然将它与普通的 static mut RES: MyResource 一起使用会导致不安全的代码,因为我们需要修改可变静态。