Rust 如何使用panic::catch_和异步代码展开?

Rust 如何使用panic::catch_和异步代码展开?,rust,async-await,Rust,Async Await,在使用同步代码时,我可以像这样使用panic::catch\u unwind: #[actix\u rt::test] 异步fn测试\u sync()->结果{ println!(“放松前”); 让sync_result=panic::catch_unwind(| |{ println!(“内部同步捕捉释放”); 恐慌!(“这是错误”) }); println!(“放松后”); 断言!(sync_result.is_ok()); 好(()) } 当处理在catch\u unwind块内执行的异

在使用同步代码时,我可以像这样使用
panic::catch\u unwind

#[actix\u rt::test]
异步fn测试\u sync()->结果{
println!(“放松前”);
让sync_result=panic::catch_unwind(| |{
println!(“内部同步捕捉释放”);
恐慌!(“这是错误”)
});
println!(“放松后”);
断言!(sync_result.is_ok());
好(())
}
当处理在
catch\u unwind
块内执行的异步代码时,如何执行相同的操作?我不知道如何运行该块,同时还能在该块之后运行一些代码并最终断言结果

这就是我到目前为止所做的:

#[actix\u rt::test]
异步fn测试\u async()->结果{
println!(“放松前”);
让async|u result=panic::catch|u展开(| | async{
println!(“内部异步捕获\u展开”);
恐慌!(“这是错误”)
}).等待;
println!(“放松后”);
断言!(async_result.is_ok());
好(())
}

I不会尝试直接使用它们。相反,使用和

使用期货::FutureExt;//0.3.5
#[东京:测试]
异步fn测试\u async()->结果{
println!(“放松前”);
让may\u panic=async{
println!(“内部异步捕获\u展开”);
恐慌!(“这是错误”)
};
让async_result=may_panic.catch_unwind().wait;
println!(“放松后”);
断言!(async_result.is_ok());
好(())
}

我遇到了这个问题,Shepmaster的回答部分有效。我得到了很多关于展开和不安全传输变量的非常复杂的描述错误。在您对公认答案的评论中,您也提到了这个问题

下面的解决方法为我解决了这个问题。我不建议在测试之外使用它,因为这种方法可能会很昂贵。它使用互斥锁和当前运行时(句柄)


谢谢,这真是太棒了!但是,对于更复杂的示例,在调用库(如sqlx)中的异步函数时,我确实会遇到错误,如“可能无法安全地跨展开边界传输”:/
use futures::FutureExt; // 0.3.5

#[tokio::test]
async fn test_async() -> Result<(), Box<dyn std::error::Error>> {
    println!("before catch_unwind");

    let may_panic = async {
        println!("inside async catch_unwind");
        panic!("this is error")
    };

    let async_result = may_panic.catch_unwind().await;

    println!("after catch_unwind");

    assert!(async_result.is_ok());

    Ok(())
}
fn main() {}

#[cfg(test)]
mod test {
    #[tokio::test]
    async fn test() {
        env_logger::init();
        // This variable represents your complex type
        // Note that this can be a combination of types if you use a tuple or something else
        let my_complex_type = 1;

        // Wrap it all in a std::sync::Mutex
        let mutex = std::sync::Mutex::new(my_complex_type);

        // Pass the mutex in the panic unwind
        assert!(std::panic::catch_unwind(|| {
            // Now you can work with your complex type
            let my_complex_type = mutex.lock().unwrap();

            // Enter the runtime
            let handle = tokio::runtime::Handle::current();

            handle.enter();

            futures::executor::block_on(do_something(*my_complex_type));
        }).is_err());
    }

    async fn do_something(t: i32) {
        panic!();
    }
}