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

Rust如何Mock reqwest::Result以返回错误类型?

如何Mock reqwest::Result返回错误类型

问题场景

你有一个封装的HTTP客户端方法api_get(以及同类型的api_post),返回reqwest::Result<T>:

pub async fn api_get<T: 'static>(&self, path: &str) -> reqwest::Result<T>
where
    T: serde::de::DeserializeOwned,
{
    let url = format!("{}/{}", self.backend_url, path);
    let response = self.client.get(&url).send().await?;
    let data = response.json::<T>().await?;
    Ok(data)
}

测试时想Mockapi_post返回错误,但尝试直接调用reqwest::Error::new失败——因为这个方法是私有的:

#[tokio::test]
async fn foo_test() {
    let mock_client = HttpClient::default();

    mock_client
        .expect_api_post()
        .returning(|_, __| reqwest::Error::new(reqwest::ErrorKind::Other, "test error"));
}

可行解决方案

方案1:用reqwest公开的错误构造方法

reqwest提供了多种公开方式创建错误,不用碰私有方法:

  • 新版本reqwest(0.11+)可以直接用Error::msg快速构造自定义错误:
#[tokio::test]
async fn foo_test() {
    let mock_client = HttpClient::default();

    mock_client
        .expect_api_post()
        .returning(|_, __| Err(reqwest::Error::msg("test error")));
}
  • 如果版本较低,可借助标准库错误转换:
use std::io;

#[tokio::test]
async fn foo_test() {
    let mock_client = HttpClient::default();

    let io_err = io::Error::new(io::ErrorKind::Other, "test error");
    mock_client
        .expect_api_post()
        .returning(|_, __| Err(reqwest::Error::from_std(io_err)));
}

方案2:Mock实际请求而非客户端方法

如果你的HttpClient内部用了reqwest::Client,可以用mockito这类库模拟错误响应,让真实的请求逻辑返回错误:

use mockito::mock;

#[tokio::test]
async fn foo_test() {
    // 模拟POST请求返回500错误
    let _mock = mock("POST", "/target-path")
        .with_status(500)
        .create();

    let client = HttpClient {
        backend_url: &mockito::server_url(),
        client: reqwest::Client::new(),
    };

    let result = client.api_post(/* 传入测试参数 */).await;
    assert!(result.is_err());
}

方案3:自定义错误类型

给HttpClient定义自己的错误枚举,实现From<reqwest::Error>,Mock时直接返回自定义错误:

#[derive(Debug)]
pub enum HttpClientError {
    TestError(String),
    Reqwest(reqwest::Error),
}

impl From<reqwest::Error> for HttpClientError {
    fn from(err: reqwest::Error) -> Self {
        HttpClientError::Reqwest(err)
    }
}

// 调整api_post的返回类型
pub async fn api_post<T: 'static>(&self, ...) -> Result<T, HttpClientError> {
    // 原有逻辑,reqwest错误会自动转换
    let response = self.client.post(...).send().await?;
    // ...
}

测试时直接返回自定义错误:

#[tokio::test]
async fn foo_test() {
    let mock_client = HttpClient::default();

    mock_client
        .expect_api_post()
        .returning(|_, __| Err(HttpClientError::TestError("test error".into())));
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 07:40:31