Rust多线程Worker测试:如何验证Job已被匿名函数正常执行
问题根因
你遇到的断言失败和无所有权报错的核心原因是:bool 类型实现了 Copy trait,当你把 state_updated 移动进闭包时,实际是隐式复制了一份全新的bool值,闭包里修改的是副本,测试主线程的原变量完全不受影响。也正因为Copy类型的移动语义是复制而非转移所有权,所以你在断言位置访问原变量不会报「移动后引用」错误。
问题1:修改方案让测试正常通过
使用 Arc<Mutex<bool>> 实现多线程共享可变状态,让测试主线程和工作线程访问同一份bool值,修改后的测试代码如下:
use std::sync::mpsc; use std::sync::Arc; use std::sync::Mutex; use hello_server_help::Worker; use std::thread; use std::time::Duration; #[test] fn test_worker_processes_job() { let (sender, r) = mpsc::channel(); let receiver = Arc::new(Mutex::new(r)); let _ = Worker::new(0, receiver); // 用Arc<Mutex>包裹bool实现多线程共享可变 let state_updated = Arc::new(Mutex::new(false)); // 克隆Arc所有权传入闭包 let state_clone = Arc::clone(&state_updated); let f = move || *state_clone.lock().unwrap() = true; sender.send(Box::new(f)).unwrap(); thread::sleep(Duration::from_secs(1)); assert_eq!(*state_updated.lock().unwrap(), true); }
问题2:更合理的测试方案
不推荐使用固定时长的sleep等待任务完成,不同机器执行性能差异很大,容易出现测试不稳定的问题,更可靠的方式是用通道做任务完成通知,不需要依赖固定等待时间:
use std::sync::mpsc; use std::sync::Arc; use std::sync::Mutex; use hello_server_help::Worker; #[test] fn test_worker_processes_job() { let (job_sender, r) = mpsc::channel(); let receiver = Arc::new(Mutex::new(r)); let _ = Worker::new(0, receiver); // 新建通道用来接收任务完成通知 let (done_sender, done_receiver) = mpsc::channel(); let f = move || { // 任务执行完成后发送通知 done_sender.send(()).unwrap(); }; job_sender.send(Box::new(f)).unwrap(); // 阻塞等待任务完成通知,收到即说明任务已执行,无多余等待 done_receiver.recv().unwrap(); }
这个方案更高效也更稳定,不会因为机器性能差异出现测试偶发失败的问题。你当前的Worker实现用了无限loop接收任务,测试跑完后工作线程会泄漏,后续加优雅停机逻辑时取出Worker的handle做join即可清理线程资源。
内容的提问来源于stack exchange,提问作者Algamest
相关产品推荐
相关产品推荐

