How to "catch" and "re-throw" a panic? (for test code)

You're talking about resume_unwind, which is the other half of catch_unwind. Run the test case inside catch_unwind, save the result, do the cleanup, then use resume_unwind to continue. Something like:

#[test]
fn crashy_test() {
    let res = std::panic::catch_unwind(|| do_crashy_test());
    clean_up_after_test();
    match res {
        Ok(ok) => it_didnt_panic(ok),
        Err(panic) => std::panic::resume_unwind(panic),
    }
}

Note, though, that this is manual and error prone. A better option is to use Drop to clean up at the end of a scope - unwinding runs Drop::drop for you:

struct Cleanup;
impl Drop for Cleanup {
    fn drop(&mut self) {
        clean_up_after_test();
    }
}

#[test]
fn crashy_test() {
    let _cleanup = Cleanup;
    let res = do_crashy_test();
    it_didnt_panic(res);
}
3 Likes