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

Rust中如何访问被Arc包裹的mockall Mock对象以调用checkpoint方法?

解决Mockall中Arc包裹Mock后无法访问的问题

方案一:用泛型让MyStruct支持具体Mock类型

把MyStruct改成泛型结构,既能在生产环境使用实现MyTrait的具体类型,测试时也能直接持有MockMyTrait的Arc引用,方便后续操作:

#[automock]
trait MyTrait {
    fn some_func(&self) -> i64;
}

// 改成泛型结构,约束T实现MyTrait
struct MyStruct<T: MyTrait> {
    data: Arc<T>
}

impl<T: MyTrait> MyStruct<T> {
    // ... 原有代码保持不变
}

#[test]
fn a_test() {
    let mut mock = MockMyTrait::new();
    mock.expect_some_func().return_const(42);
    // 克隆一个Arc,后续用来操作mock
    let mock_arc = Arc::new(mock);
    let testee = MyStruct { data: Arc::clone(&mock_arc) };

    // 执行MyStruct的测试代码

    // 通过mock_arc获取可变引用,需要用Arc::get_mut
    if let Some(mock_mut) = Arc::get_mut(&mut mock_arc) {
        mock_mut.checkpoint();
        mock_mut.expect_some_func().return_const(100);
    }

    // 继续执行后续测试代码
}

这个方案类型安全,不需要额外类型转换,生产环境可以正常使用MyStruct<RealImpl>的形式。

方案二:使用Arc的downcast方法转换类型

如果不想修改MyStruct的定义,保持Arc<dyn MyTrait>的话,可以用Arc::downcast把trait对象转成具体的Mock类型:

#[automock]
trait MyTrait {
    fn some_func(&self) -> i64;
}

struct MyStruct {
    data: Arc<dyn MyTrait>
}

impl MyStruct {
    // ... 原有代码
}

#[test]
fn a_test() {
    let mut mock = MockMyTrait::new();
    mock.expect_some_func().return_const(42);
    let mock_arc = Arc::new(mock);
    let testee = MyStruct { data: Arc::clone(&mock_arc) };

    // 执行MyStruct的测试代码

    // 测试环境中可以直接unwrap,因为确定是Mock类型
    let mut mock_mut = Arc::get_mut(&mut mock_arc).unwrap();
    mock_mut.checkpoint();
    mock_mut.expect_some_func().return_const(100);

    // 继续执行后续测试代码
}

如果测试场景中需要多个Arc引用,Arc::get_mut会返回None,这时可以把Mock包在Mutex里:

#[test]
fn a_test_with_mutex() {
    let mock = MockMyTrait::new();
    let mock_arc_mutex = Arc::new(Mutex::new(mock));
    let testee = MyStruct { 
        data: Arc::clone(&mock_arc_mutex) as Arc<dyn MyTrait> 
    };

    // 执行测试代码

    // 锁定Mutex获取可变引用
    let mut mock_mut = mock_arc_mutex.lock().unwrap();
    mock_mut.checkpoint();
    mock_mut.expect_some_func().return_const(200);

    // 继续测试
}

小结

  • 能修改MyStruct定义的话,泛型方案是最清晰、类型安全的选择。
  • 不能修改结构时,downcast或Mutex包裹Mock都能解决问题,后者适合多线程或多引用的场景。

内容的提问来源于stack exchange,提问作者ptriller

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 09:25:21