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

使用Rust Mockall crate时returning方法未找到的问题求助

Mockall中returning方法找不到的问题解决

问题场景

定义的Reader trait及实现:

#[cfg_attr(test, automock)]
pub trait Reader {
    fn next_data(&mut self) -> &Data;
}

impl Reader for TestReader {
    fn next_data(&mut self) -> &Data {
        let data: &Data = &self.data[self.index];
        self.index += 1;
        data
    }
}

测试代码尝试配置MockReader时出错:

fn test_reader() {
    let data_iter: IntoIter<Data> = (some vector Vec<Data>).into_iter();
    let mut reader = MockReader::new();
    reader
        .expect_next_data()
        .times(2)
        .returning(move || data_iter.clone().next().is_some());
}

收到错误:

error[E0599]: no method named `returning` found for mutable reference `&mut __mock_MockReader_Reader::__next_data::Expectation` in the current scope
   --> src/tests/test_data.rs:177:14
    |
174 | /         reader
175 | |             .expect_next_data()
176 | |             .times(2)
177 | |             .returning(move || data_iter.clone().next().is_some());
    | |             -^^^^^^^^^ method not found in `&mut Expectation`
    | |_____________|
    | 

错误原因

  • 返回值类型不匹配:原trait方法next_data的返回值是&Data,但测试中闭包返回的是bool(is_some()的结果)。Mockall会根据trait方法的签名生成对应的Expectation类型,只有当闭包返回值类型与trait方法完全一致时,才会存在对应的returning方法。类型不匹配时,编译器找不到该方法。
  • 迭代器使用错误:IntoIter<Data>是拥有所有权的迭代器,clone()需要Data实现Clone trait,且即使克隆,返回的是Data实例而非引用,和原方法的返回类型不符。

解决方案

1. 修正返回值类型,匹配trait方法签名

确保闭包返回&Data类型,同时保证数据的生命周期足够覆盖测试过程。示例代码:

fn test_reader() {
    // 初始化测试数据,放在栈上保证生命周期
    let data_vec = vec![Data { /* 初始化字段 */ }, Data { /* 初始化字段 */ }];
    // 使用iter()获取&Data的迭代器
    let mut data_iter = data_vec.iter();

    let mut reader = MockReader::new();
    reader
        .expect_next_data()
        .times(2)
        .returning(move || {
            // 这里unwrap()假设我们确定有足够的元素,也可以用expect()处理测试失败
            data_iter.next().expect("Insufficient data in iterator")
        });
}

2. 处理多次调用的引用返回(可选)

如果需要更灵活地处理引用返回,也可以使用Mockall提供的returning_ref方法(当返回引用时更直观):

fn test_reader() {
    let data = Data { /* 初始化字段 */ };
    let mut reader = MockReader::new();
    reader
        .expect_next_data()
        .times(2)
        .returning_ref(&data);
}

3. 注意迭代器的生命周期

确保迭代器引用的数据不会在测试过程中被释放,比如将数据放在测试函数的栈上,避免使用临时变量导致生命周期不足。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 15:18:12