You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 22:27:04