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
相关产品推荐
相关产品推荐

