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

Rust嵌套Mock方法预期设置报错及解决方案

问题描述

尝试Mock一个返回另一个Mock对象的trait方法时失败,出现错误:

no method named `returning` found for mutable reference `&mut __get_account_query::Expectation` in the current scope
method not found in `&mut Expectation`

处理程序代码

pub struct AppState {
    db: Box<dyn QueryDependency>,
}

#[post("/create")]
pub async fn create_account(
    data: web::Data<AppState>
) -> impl Responder {
     ..... 
     .....
    let result = data.db.get_account_query().create_account(&new_account).await;
                           // 尝试Mock的函数
}  


#[actix_web::test]
async fn create_account_test() {
        let mock_db = MockQueryDependency::new();
        let mut mock_account_query = MockAccountQuery::new();

        mock_account_query
            .expect_create_account()
            .times(1)
            .returning(|_| Ok(Account {
                id: 1,
                name: "test".to_string(),
            }));
        
        mock_db.expect_get_account_query().times(1).returning(|| &mock_account_query);

        let mock_state = AppState {
            db: Box::new(mock_db),
        };
}

Trait定义

#[cfg(test)]
use mockall::automock;

#[cfg_attr(test, automock)]
pub trait QueryDependency: Send + Sync {
    fn get_account_query(&self) -> &dyn AccountQuery;
}

#[cfg_attr(test, automock)]
#[async_trait]
pub trait AccountQuery: Send + Sync {
    async fn create_account(&self, new_account: &NewAccount) -> Result<Account, sqlx::Error>;
}
解决方法

核心问题

错误源于QueryDependency的get_account_query方法返回引用类型,直接返回局部MockAccountQuery实例的引用会触发生命周期不匹配,同时mockall对返回引用的方法的Expectation类型不支持直接使用returning方法。

具体修复步骤

  1. 用Arc共享Mock实例:通过Arc包裹MockAccountQuery,确保引用生命周期与MockQueryDependency匹配,避免所有权问题。
  2. 调整mock返回逻辑:使用move闭包配合Arc::as_ref返回符合要求的引用。

修改后的测试代码:

use std::sync::Arc;

#[actix_web::test]
async fn create_account_test() {
    // 用Arc包裹MockAccountQuery,实现共享所有权
    let mock_account_query = Arc::new(MockAccountQuery::new());
    // 克隆Arc用于设置create_account的期望(原Arc会被move到闭包中)
    let mut mock_account_query_clone = Arc::clone(&mock_account_query);

    // 设置create_account的调用期望
    mock_account_query_clone
        .expect_create_account()
        .times(1)
        .returning(|_| Ok(Account {
            id: 1,
            name: "test".to_string(),
        }));
    
    let mut mock_db = MockQueryDependency::new();
    // 设置get_account_query的返回,用move闭包返回Arc的引用
    mock_db.expect_get_account_query()
        .times(1)
        .returning(move || Arc::as_ref(&mock_account_query));

    let mock_state = AppState {
        db: Box::new(mock_db),
    };

    // 此处可添加发送请求并验证结果的代码
}

额外说明

  • 如果允许修改原trait,可将get_account_query的返回类型改为Arc<dyn AccountQuery>,这样mock时无需处理引用,直接返回Arc实例即可,代码会更简洁。
  • 确保使用较新版本的mockall,旧版本对返回引用的方法支持可能存在缺陷。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 06:34:58