在Rust测试中,有没有办法检查调用std::process::exit()
的函数是否真的用特定的退出代码终止了进程?
受挫的例子:
fn foo(n: i32) {
std::process::exit(n);
}
#[test]
fn exits_with_correct_exit_code() {
// How do I assert that the following call terminates
// the process with exit code 1?
foo(1);
}
答案 0 :(得分:3)
你做不到。 std::process:exit
的名字很有名,但是如果不清楚它的作用是什么方式:
使用指定的退出代码终止当前进程。
此功能永远不会返回并立即终止 目前的过程。退出代码将传递到底层操作系统 并可供其他流程使用。
请注意,因为此函数永远不会返回,并且它会终止 进程,当前堆栈或任何其他线程没有析构函数 堆栈将运行。如果需要干净关机,建议使用 只在没有更多的已知点调用此函数 破坏者离开了。
运行测试时,每个测试都在一个单独的线程中运行,但所有测试都在一个进程中运行。当该过程终止时,测试就随之进行。
您可以尝试进行一些复杂的递归测试:
#[test]
#[ignore]
fn real() {
std::process::exit(42)
}
#[test]
fn shim() {
let status = std::process::Command::new("/proc/self/exe")
.args(&["--ignored", "real"])
.status()
.expect("Unable to run program");
assert_eq!(Some(42), status.code());
}
这有特定于平台的代码来查找当前进程,但它可以正常工作"。
老实说,我说代码超出了测试范围。你不应该测试std::process::exit
做了它会说的那样。如果你真的需要断言用一个参数调用一个函数,那就是mock object的用途。
使用依赖注入来提供闭包,捕获闭包中的值,并编写一个薄的垫片:
fn foo_logic<F>(n: i32, f: F)
where F: FnOnce(i32)
{
f(n);
}
fn foo(n: i32) {
foo_logic(n, |n| std::process::exit(n));
}
#[test]
fn exits_with_correct_exit_code() {
let mut value = None;
foo_logic(1, |v| value = Some(v));
assert_eq!(Some(1), value);
}
您也可以考虑提取计算潜在错误代码并直接测试的逻辑。