Rust Mock 工具
Rust Mock 工具
Mock(模拟)是测试中不可或缺的工具,用来替代复杂或不可控的依赖,比如数据库、网络服务等,帮助我们写出高质量、健壮的测试代码。Rust 社区中,mockall
和 mockito
是两款主流且强大的 Mock 库,分别针对 trait 依赖和 HTTP 请求。
目录
-
Mock 基础理解与意义
-
mockall
:Rust Trait Mock 实战- 2.1 安装与基本用法
- 2.2 参数匹配器技巧
- 2.3 调用次数与顺序控制
- 2.4 返回值高级控制
- 2.5 异步函数 Mock
- 2.6 手写 Mock vs 自动生成 Mock
- 2.7 常见坑与调试技巧
-
mockito
:HTTP 请求 Mock 实战- 3.1 安装与基础用法
- 3.2 匹配请求头、请求体及路径参数
- 3.3 模拟网络延迟与错误
- 3.4 多个 Mock 交互与验证调用顺序
1. Mock 基础理解与意义
-
为什么要用 Mock?
测试真实依赖(数据库、网络)通常会慢、不稳定,且不易覆盖异常路径。Mock 允许我们模拟依赖行为,快速且精准地测试业务逻辑。 -
Mock 和 Stub 的区别?
Stub 只是返回预设结果的替身,Mock 除了返回结果,还能验证调用是否发生、参数是否正确、调用顺序等。 -
Rust Mock 工具特点
Rust 静态类型强且拥有 trait 机制,Mock 库多基于 trait 来实现替身行为,网络请求 Mock 则独立存在。
2. mockall:Trait Mock 实战
mockall
通过 #[automock]
宏自动生成 Mock 结构体,支持丰富的匹配和返回值设置。
2.1 安装与基础用法
Cargo.toml
:
[dev-dependencies]
mockall = "0.11"
示例:
use mockall::{automock, predicate::*};#[automock]
pub trait UserRepo {fn find_user(&self, user_id: u32) -> Option<String>;
}#[cfg(test)]
mod tests {use super::*;#[test]fn basic_mock() {let mut mock = MockUserRepo::new();mock.expect_find_user().with(predicate::eq(42)).times(1).returning(|_| Some("Alice".to_string()));assert_eq!(mock.find_user(42), Some("Alice".to_string()));}
}
2.2 参数匹配器技巧
mockall 提供丰富参数匹配器 predicate
,常用:
predicate::eq(value)
- 等于predicate::always()
- 任意参数都匹配predicate::lt(value)
,gt()
,le()
,ge()
- 大小比较- 自定义闭包匹配
predicate::function(|arg| ...)
示例:
mock.expect_find_user().with(predicate::function(|id| *id > 0)).returning(|id| Some(format!("User{}", id)));
2.3 调用次数与顺序控制
.times(n)
指定调用次数.once()
等价.times(1)
.never()
期望不被调用.in_sequence(&mut seq)
用于控制调用顺序(配合Sequence
类型)
示例:
use mockall::Sequence;let mut seq = Sequence::new();mock.expect_find_user().with(predicate::eq(1)).times(1).in_sequence(&mut seq).returning(|_| Some("First".to_string()));mock.expect_find_user().with(predicate::eq(2)).times(1).in_sequence(&mut seq).returning(|_| Some("Second".to_string()));
这样会验证先调用参数1再调用参数2。
2.4 返回值高级控制
.returning()
支持闭包返回不同结果.return_once()
返回一次后失效,之后走.returning()
默认行为.panic()
用于模拟异常
示例:
mock.expect_find_user().with(predicate::eq(1)).return_once(|_| Some("One".to_string())).return_once(|_| Some("Two".to_string())).returning(|_| None);
2.5 异步函数 Mock
支持 async trait:
use std::future::Future;
use std::pin::Pin;#[automock]
trait AsyncTrait {fn fetch(&self) -> Pin<Box<dyn Future<Output=String> + Send>>;
}#[tokio::test]
async fn async_mock_test() {let mut mock = MockAsyncTrait::new();mock.expect_fetch().returning(|| Box::pin(async { "async result".to_string() }));let res = mock.fetch().await;assert_eq!(res, "async result");
}
2.6 手写 Mock vs 自动生成 Mock
- 自动生成方便快捷,推荐用
#[automock]
- 手写 Mock 更灵活,适合复杂场景或无 trait 的情况
手写示例:
struct ManualMock;impl UserRepo for ManualMock {fn find_user(&self, user_id: u32) -> Option<String> {if user_id == 42 { Some("Manual".to_string()) } else { None }}
}
2.7 常见坑与调试技巧
times()
配置不当导致测试失败:检查调用次数是否和预期匹配- 调用顺序不对:用
Sequence
管理调用顺序 - 参数匹配失败:用
.with(predicate::always())
暂时放宽匹配,确认调用 - 调试信息:Rust 测试输出可用
println!
配合 Mock 函数打印确认执行流程
3. mockito:HTTP 请求 Mock
3.1 安装
[dev-dependencies]
mockito = "0.31"
3.2 简单示例
#[cfg(test)]
mod tests {use mockito::mock;#[test]fn http_mock() {let _m = mock("GET", "/api/user/42").with_status(200).with_body(r#"{"name":"Alice"}"#).create();let url = format!("{}/api/user/42", mockito::server_url());let resp = reqwest::blocking::get(&url).unwrap();let body = resp.text().unwrap();assert_eq!(body, r#"{"name":"Alice"}"#);}
}
3.3 复杂匹配
- 匹配请求头
mock("POST", "/submit").match_header("content-type", "application/json").with_status(201).create();
- 匹配请求体
use mockito::Matcher;mock("POST", "/submit").match_body(Matcher::JsonString(r#"{"key":"value"}"#.to_string())).with_status(201).create();
3.4 模拟延时、失败
mock("GET", "/slow").with_status(200).with_body("delayed").with_delay(std::time::Duration::from_secs(3)).create();
模拟网络错误:
mock("GET", "/fail").with_status(500).with_body("Internal Server Error").create();
3.5 多个 Mock 与调用顺序
let _m1 = mock("GET", "/step1").with_status(200).with_body("first").create();let _m2 = mock("GET", "/step2").with_status(200).with_body("second").create();
请求 /step1
和 /step2
会匹配对应 Mock。
相关文章:
Rust Mock 工具
Rust Mock 工具 Mock(模拟)是测试中不可或缺的工具,用来替代复杂或不可控的依赖,比如数据库、网络服务等,帮助我们写出高质量、健壮的测试代码。Rust 社区中,mockall 和 mockito 是两款主流且强大的 Mock …...
C++读写锁以及实现方式
文章目录 【C专题】读写锁(Reader-Writer Lock)原理与实现方式(含C11/20实践)一、读写锁核心概念1. **什么是读写锁?**2. **读写锁 vs 互斥锁** 二、C中的读写锁实现方式 方案一:POSIX 读写锁(p…...

Electron-vite【实战】MD 编辑器 -- 文件列表(含右键快捷菜单,重命名文件,删除本地文件,打开本地目录等)
最终效果 页面 src/renderer/src/App.vue <div class"dirPanel"><div class"panelTitle">文件列表</div><div class"searchFileBox"><Icon class"searchFileInputIcon" icon"material-symbols-light:…...

华为云Flexus+DeepSeek征文|华为云Flexus云服务器X实例上部署Dify:打造高效的开源大语言模型应用开发平台
目录 前言 1 Dify与华为云部署概述 1.1 什么是 Dify 1.2 华为云与 Flexus 云服务器的优势 2 云服务器部署 Dify 的步骤详解 2.1 模板选择 2.2 参数配置 2.3 资源栈设置 2.4 确认部署信息并执行 3 部署成功后的操作与平台使用指南 3.1 访问平台 3.2 设置管理员账号 …...
[git每日一句]Your branch is up to date with ‘origin/master‘
这句话是 Git 版本控制系统的提示信息,意思是: "你当前所在的分支已经与远程仓库(origin)的 master 分支同步,没有需要推送的提交。" 详细解释: Your branch - 指你当前所在的本地分支 is up …...

高密爆炸警钟长鸣:AI为化工安全戴上“智能护盾”
一、高密爆炸:一声巨响,撕开化工安全“伤疤” 2025年5月27日,山东高密友道化学有限公司的车间爆炸声,像一把利刃划破了化工行业的平静。剧烈的冲击波将车间夷为平地,黑色蘑菇云腾空而起,刺鼻的化学气味弥漫…...

机器人学基础——正运动学(理论推导及c++实现)
机器人正运动学 机器人正运动学一般是指从机器人的关节位置到基于参考坐标系下末端执行器的位置。 平移变换和旋转变换 平移变换 假设我们有两个坐标系A和B,坐标系A与B的方位相同,xyz轴的指向都是一致的,即没有旋转变换。有一点p…...

[网页五子棋][对战模块]处理连接成功,通知玩家就绪,逻辑问题(线程安全,先手判定错误)
文章目录 处理连接成功通知玩家就绪逻辑图问题 1:线程安全问题 2:先手判定错误两边都是提示:轮到对方落子 处理连接成功 实现 GameAPI 的 afterC…...
TensorFlow Extended (TFX) 生产环境模型版本控制与回滚实战指南
TFX 版本控制核心架构 TFX 通过以下组件构建完整的模型生命周期管理系统: ML Metadata (MLMD):记录所有实验和管道的元数据Pusher 组件:负责模型部署与版本标记Model Registry:集中式模型存储库&#x…...

【Web应用】若依框架:基础篇11功能详解-系统接口
文章目录 ⭐前言⭐一、课程讲解⭐二、自己动手实操⭐总结 标题详情作者JosieBook头衔CSDN博客专家资格、阿里云社区专家博主、软件设计工程师博客内容开源、框架、软件工程、全栈(,NET/Java/Python/C)、数据库、操作系统、大数据、人工智能、工控、网络、…...

【Docker项目实战篇】Docker部署PDF查看器PdfDing
【Docker项目实战篇】Docker部署PDD查看器PdfDing 一、PdfDing介绍1.1 PdfDing简介1.2 PdfDing主要特点1.3 主要使用场景 二、本次实践规划2.1 本地环境规划2.2 本次实践介绍 三、本地环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker compose 版本 四、下载Pd…...
Redis 常用数据类型和命令使用
目录 1 string 2 hash 3 list 4 set集合 5 zset有序集合 1 string 值可以是字符串、数字和二进制的value,值最大不能超过512MB 应用场景: 应用程序缓存 计数器 web共享session 限速 1.1 设置单个键值 set <key> value [EX seconds|PX…...

【Linux系统】第八节—进程概念(上)—冯诺依曼体系结构+操作系统+进程及进程状态+僵尸进程—详解!
hi,我是云边有个稻草人 偶尔中二的博主^(* ̄(oo) ̄)^,与你分享专业知识,祝博主们端午节快乐! Linux—本节博客所属专栏—持续更新中—欢迎订阅! 目录 一、冯诺依曼体系结构 二、操作系统(Opera…...
WPF 全局加载界面、多界面实现渐变过渡效果
WPF 全局加载界面与渐变过渡效果 完整实现方案 MainWindow.xaml <Window x:Class"LoadingScreenDemo.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/2006/xaml&quo…...
WebSocket与实时对话式AI服务的集成
WebSocket与实时对话式AI服务的集成 在现代对话式AI系统中,传统的HTTP请求-响应模型已难以满足实时交互的体验需求。特别是用户对响应速度、逐字输出、会话上下文保持等方面提出更高要求时,需要一种能够建立持久连接并支持双向通信的协议。WebSocket正是在这一背景下,成为A…...
【xmb】】内部文档148344599
这里写自定义目录标题 CyberDog 2 仿真智能物流配送系统 – 初赛设计报告摘要目录1 引言2 任务与需求分析3 系统总体设计4 核心算法与模块实现5 仿真测试与结果分析6 结论与展望 CyberDog 2 仿真智能物流配送系统 – 初赛设计报告 团队名称: (晚点写&am…...
MobaXterm国内下载与安装使用教程
MobaXterm是一款为 Windows 用户量身打造的远程终端工具,它将多种网络功能集成在一个轻量级、便携式的界面中,尤其适合需要频繁与远程主机交互的开发者、系统运维工程师以及科研技术人员。无论是管理 Linux 服务器、远程执行命令,还是图形化运…...

数据结构——优先级队列(PriorityQueue)
1.优先级队列 优先级队列可以看作队列的另一个版本,队列的返回元素是由是由插入顺序决定的,先进先出嘛,但是有时我们可能想要返回优先级较高的元素,比如最大值?这种场景下就由优先级队列登场。 优先级队列底层是由堆实…...

代谢组数据分析(二十六):LC-MS/MS代谢组学和脂质组学数据的分析流程
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍加载R包依赖包安装包加载需要的R包数据下载以及转换mzML数据预处理代谢物注释LipidFinder过滤MultiABLER数据预处理过滤补缺失值对数变换数据标准化下游数据分析总结系统信息参考介…...
服务器上用脚本跑python深度学习的注意事项(ubantu系统)
bash: $\r: command not found 问题原因: 出现 bash: $\r: command not found 以及路径中出现 \r 通常是因为脚本文件是在Windows系统下编辑,然后在Linux(如Ubuntu)系统中运行。在Windows系统中,文本文件的换行符是 \…...

【ARM】【FPGA】【硬件开发】Chapter.1 AXI4总线协议
Chapter.1 AXI4总线协议 作者:齐花Guyc(CAUC) 一、总线介绍 AXI4总线 AXI4总线就像是SoC内部的“高速公路”,负责在不同硬件模块之间高效传输数据。 AXI4协议通过 5个独立通道 传输数据和控制信号,每个通道都有自己的信号线,互…...
青少年编程与数学 02-020 C#程序设计基础 10课题、桌面应用开发
青少年编程与数学 02-020 C#程序设计基础 10课题、桌面应用开发 一、桌面应用1. 主要特点2. 常见类型3. 优势4. 局限性 二、开发步骤1. 准备工作2. 创建项目3. 开发应用4. 运行调试5. 打包发布 三、Windows 窗体应用(一)定义(二)特…...

把 jar 打包成 exe
1. 把自己的项目先正常打成jar包 2. 使用exe4j工具将jar转换为exe 2.1 exe4j下载地址:https://www.ej-technologies.com/download/exe4j/files 2.2 下载完成之后激活 2.3 可以点击Change License,输入秘钥L-g782dn2d-1f1yqxx1rv1sqd 2.4 直接下一步…...

【目标检测】检测网络中neck的核心作用
1. neck最主要的作用就是特征融合,融合就是将具有不同大小感受野的特征图进行了耦合,从而增强了特征图的表达能力。 2. neck决定了head的数量,进而潜在决定了不同尺度样本如何分配到不同的head,这一点可以看做是将整个网络的多尺…...

【经验】Ubuntu中设置terminator的滚动行数、从Virtualbox复制到Windows时每行后多一空行
1、设置terminator的滚动行数 1.1 问题描述 在终端 terminator 中,调试程序时,只能查看有限行数的打印日志,大约是500行,怎么能增加行数 1.2 解决方法 1)安装terminator sudo apt install terminator和 terminato…...

使用微软最近开源的WSL在Windows上优雅的运行Linux
install wsl https://github.com/microsoft/WSL/releases/download/2.4.13/wsl.2.4.13.0.x64.msi install any distribution from microsoft store, such as kali-linux from Kali office website list of distribution PS C:\Users\50240> wsl -l -o 以下是可安装的有…...

HackMyVM-Teacher
信息搜集 主机发现 ┌──(kali㉿kali)-[~] └─$ nmap -sn 192.168.43.0/24 Starting Nmap 7.95 ( https://nmap.org ) at 2025-06-01 01:02 EDT Nmap scan report for 192.168.43.1 Host is up (0.0084s latency). MAC Address: C6:45:66:05:91:88 (Unknow…...

BugKu Web渗透之矛盾
开启场景,打开网页。发现是一段php代码。 这段代码也很好理解,就是get方式传参num,如果num不是数字类型,那么输出num的值,并且num1时,输出flag的值。 首先看看is_numeric的意思。 开始我想到了使用科学技术…...
hot100 -- 4.子串系列
1.和为 K 的子数组 问题: 给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 。 子数组是数组中元素的连续非空序列。 方法1:暴力枚举 # 方法1:暴力枚举(遍历子数组起点和终点&…...

Python实现P-PSO优化算法优化卷积神经网络CNN回归模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 随着人工智能和深度学习技术的快速发展,卷积神经网络(CNN)在图像分类、目标检测…...