2.1 Mockito核心API详解

Mockito核心API详解

1. 创建Mock对象

Mockito提供两种方式创建模拟对象:

1.1 手动创建(传统方式)
// 创建接口/类的Mock对象
UserDao userDao = Mockito.mock(UserDao.class);
1.2 注解驱动(推荐方式)

结合JUnit 5的扩展机制,自动管理Mock生命周期:

@ExtendWith(MockitoExtension.class) // 启用Mockito支持
class UserServiceTest {@Mock // 自动创建Mock对象private UserDao mockUserDao;@InjectMocks // 自动注入@Mock对象到被测类private UserService userService;
}

选择策略

  • 简单测试 → 手动创建
  • 多依赖测试 → 注解驱动(避免重复代码)

2. 方法桩(Stubbing)

控制Mock对象方法的返回值或异常抛出。

2.1 基础配置
// 返回固定值
when(mockUserDao.findById(1)).thenReturn(new User("Alice"));// 抛出异常
when(mockUserDao.save(any())).thenThrow(new DatabaseException());// 连续配置(依次返回)
when(mockList.get(0)).thenReturn("A", "B", "C"); // 第一次"A",第二次"B"...
2.2 动态响应
// 根据输入参数动态计算返回值
when(mockCalculator.add(anyInt(), anyInt())).thenAnswer(invocation -> {int a = invocation.getArgument(0);int b = invocation.getArgument(1);return a + b;
});// 调用真实方法(部分保留逻辑)
when(mockUserDao.findById(1)).thenCallRealMethod();
2.3 Void方法处理
// 默认不做任何事情
doNothing().when(mockLogger).writeLog(anyString());// 抛出异常
doThrow(new IOException()).when(mockFileService).deleteFile(any());

3. 验证交互行为

验证Mock对象的方法是否按预期被调用。

3.1 基础验证
verify(mockUserDao).findById(1); // 验证方法被调用一次
3.2 调用次数验证
verify(mockUserDao, times(2)).update(any()); // 精确次数
verify(mockUserDao, atLeastOnce()).delete(5); // 至少一次
verify(mockUserDao, never()).findAll(); // 从未调用
3.3 顺序验证
InOrder inOrder = inOrder(mockA, mockB);
inOrder.verify(mockA).prepare();
inOrder.verify(mockB).execute();
3.4 超时验证(异步场景)
// 200ms内至少调用一次
verify(mockAsyncService, timeout(200)).callback();

4. 参数匹配器(Argument Matchers)

灵活匹配方法参数,增强测试的适应性和可读性。

4.1 内置匹配器
// 任意字符串参数
when(mockUserDao.findByUsername(anyString())).thenReturn(...);// 混合精确与模糊匹配
when(service.process(eq("order"), anyInt())).thenReturn(true);
4.2 自定义匹配器
// 定义复杂参数条件
verify(mockValidator).validate(argThat(user -> user.getAge() > 18 && user.isVerified()
));

注意事项

  • 若方法中多个参数使用匹配器,所有参数必须都用匹配器
  • 避免过度使用any() → 可能导致测试条件过于宽松

5. 高级功能API
5.1 Spy对象(部分真实对象)
List<String> realList = new ArrayList<>();
List<String> spyList = spy(realList); // 保留真实方法// 覆盖特定方法行为
doReturn(false).when(spyList).isEmpty(); 
5.2 参数捕获(ArgumentCaptor)
@Captor // 自动初始化
private ArgumentCaptor<User> userCaptor;@Test
void testSaveUser() {userService.register("Bob");verify(mockUserDao).save(userCaptor.capture());User capturedUser = userCaptor.getValue();assertEquals("Bob", capturedUser.getName());
}
5.3 重置Mock状态
reset(mockUserDao); // 慎用!通常表示测试设计有问题

核心API对照表

API典型应用场景
mock() / @Mock创建完全模拟的假对象
when().thenReturn()配置方法返回固定值
verify()验证方法调用情况
any() / eq()参数灵活匹配
@Spy需要保留部分真实逻辑的对象
ArgumentCaptor深入分析传入方法的参数内容

最佳实践建议

  1. 优先使用注解驱动
    @Mock + @InjectMocks 提升代码可读性和维护性。
  2. 精确验证参数
    避免过度使用any(),尽可能用eq()或具体值匹配关键参数。
  3. 及时清理过时桩
    使用Mockito.clearInvocations(mock) 而非reset()
  4. 保持测试原子性
    每个测试方法只验证一个明确的业务场景。

通过掌握这些核心API,开发者可以高效构建可靠、易维护的单元测试体系。接下来可进入参数匹配器实战学习更精细的控制技巧。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/15419.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Json-RPC框架项目(一)

目录 1. 项目介绍: 2. 技术选择; 3. 第三方库介绍; 4. 项目功能; 5. 模块功能; 6. 项目实现: 1. 项目介绍: RPC是远程过程调用, 像调用本地接口一样调用远程接口, 进行完成业务处理, 计算任务等, 一个完整的RPC包括: 序列化协议, 通信协议, 连接复用, 服务注册, 服务发…

Discourse 创建和配置用户自定义字段

用户自定义字段能够让你在用户注册的是要求用户提供更多的信息。这些用户提供的信息可以在用户名片&#xff0c;用户摘要页面下显示&#xff0c;甚至还可以通过 Data Explorer plugin 插件进行查询。 本文能够帮助你对这些字段进行配置和设置。 添加一个用户字段 进入 Admin…

从零到一:我的元宵灯谜小程序诞生记

缘起&#xff1a;一碗汤圆引发的灵感 去年元宵节&#xff0c;我正捧着热腾腾的汤圆刷朋友圈&#xff0c;满屏都是"转发锦鲤求灯谜答案"的动态。看着大家对着手机手忙脚乱地切换浏览器查答案&#xff0c;我突然拍案而起&#xff1a;为什么不做一个能即时猜灯谜的微信…

【C++11】lambda和包装器

1.新的类功能 1.1默认的移动构造和移动赋值 原来C类中&#xff0c;有6个默认成员函数&#xff1a;构造函数/析构函数/拷⻉构造函数/拷⻉赋值重载/取地址重 载/const 取地址重载&#xff0c;最后重要的是前4个&#xff0c;后两个⽤处不⼤&#xff0c;默认成员函数就是我们不写…

Java企业电子招投标系统:Spring Cloud微服务架构-强化企业招采竞争力:电子化招投标平台助力效率与成本控制-支持二次开发

​在当今激烈的市场竞争环境下&#xff0c;企业规模的持续扩大使得招采管理变得日益重要&#xff0c;已成为企业提升核心竞争力的关键一环。为了实现更高效、更高质量的招采成果&#xff0c;我们设计了一套基于电子化平台的解决方案&#xff0c;旨在通过电子化招投标系统&#…

计算机毕业设计Spark+大模型知网文献论文推荐系统 知识图谱 知网爬虫 知网数据分析 知网大数据 知网可视化 预测系统 大数据毕业设计 机器学习

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

打家劫舍3

今天和打家讲一下打家劫舍3 题目&#xff1a; 题目链接&#xff1a;337. 打家劫舍 III - 力扣&#xff08;LeetCode&#xff09; 小偷又发现了一个新的可行窃的地区。这个地区只有一个入口&#xff0c;我们称之为root。 除了 root 之外&#xff0c;每栋房子有且只有一个“父“…

指定路径安装Ollama

通过鼠标双击安装&#xff0c;默认会安装到C盘下&#xff0c;如果需要更换默认路径则可以通过命令的方式将Ollama安装到其他盘的某个目录下。 OllamaSetup.exe /DIR"D:\Ollama" #DIR指定安装路径 执行上述命令后&#xff0c;会弹出OllamaSetup.exe安装窗体界面&…

Linux:库

目录 静态库 动态库 目标文件 ELF文件 ELF形成可执行 ELF可执行加载 ELF加载 全局偏移量表GOT(global offset table) 库是写好的&#xff0c;成熟的&#xff0c;可以复用的代码 现实中每个程序都要依赖很多的基础的底层库&#xff0c;不可能都是从零开始的 库有两种…

心脏滴血漏洞复现(CVE-2014-0160)

漏洞范围&#xff1a; OpenSSL 1.0.1版本 漏洞成因&#xff1a; Heartbleed漏洞是由于未能在memcpy()调用受害用户输入内容作为长度参数之前正确进 行边界检查。攻击者可以追踪OpenSSL所分配的64KB缓存、将超出必要范围的字节信息复 制到缓存当中再返回缓存内容&#xff0c;…

一文学会:用DeepSeek R1/V3 + AnythingLLM + Ollama 打造本地化部署的个人/企业知识库,无须担心数据上传云端的泄露问题

文章目录 前言一、AnythingLLM 简介&基础应用1.主要特性2.下载与安装3.配置 LLM 提供商4.AnythingLLM 工作区&对话 二、AnythingLLM 进阶应用&#xff1a;知识增强使用三、AnythingLLM 的 API 访问四、小结1.聊天模式2.本地存储&向量数据库 前言 如果你不知道Olla…

0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 0基础…

探秘AES加密算法:多种Transformation全解析

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/literature?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;…

html文件怎么转换成pdf文件,2025最新教程

将HTML文件转换成PDF文件&#xff0c;可以采取以下几种方法&#xff1a; 一、使用浏览器内置功能 打开HTML文件&#xff1a;在Chrome、Firefox、IE等浏览器中打开需要转换的HTML文件。打印对话框&#xff1a;按下CtrlP&#xff08;Windows&#xff09;或CommandP&#xff08;M…

DFS+回溯+剪枝(深度优先搜索)——搜索算法

DFS也就是深度优先搜索&#xff0c;比如二叉树的前&#xff0c;中&#xff0c;后序遍历都属于DFS。其本质是递归&#xff0c;要学好DFS首先需要掌握递归。接下来咱们就一起来学习DFS涉及的算法。 一、递归 1.什么是递归&#xff1f; 递归可以这样理解把它拆分出来&#xff0…

DeepSeek从入门到精通教程PDF清华大学出版

DeepSeek爆火以来&#xff0c;各种应用方式层出不穷&#xff0c;对于很多人来说&#xff0c;还是特别模糊&#xff0c;有种雾里看花水中望月的感觉。 最近&#xff0c;清华大学新闻与传播学院新媒体研究中心&#xff0c;推出了一篇DeepSeek的使用教程&#xff0c;从最基础的是…

idea Ai工具通义灵码,Copilot我的使用方法以及比较

我用过多个idea Ai 编程工具&#xff0c;大约用了1年时间&#xff0c;来体会他们那个好用&#xff0c;以下只是针对我个人的一点分享&#xff0c;不一定对你适用 仅作参考。 介于篇幅原因我觉得能说上好用的 目前只有两个 一个是阿里的通义灵码和Copilot&#xff0c;我用它来干…

C++ Primer sizeof运算符

欢迎阅读我的 【CPrimer】专栏 专栏简介&#xff1a;本专栏主要面向C初学者&#xff0c;解释C的一些基本概念和基础语言特性&#xff0c;涉及C标准库的用法&#xff0c;面向对象特性&#xff0c;泛型特性高级用法。通过使用标准库中定义的抽象设施&#xff0c;使你更加适应高级…

【C++】命名空间

&#x1f31f; Hello&#xff0c;我是egoist2023&#xff01; &#x1f30d; 种一棵树最好是十年前&#xff0c;其次是现在&#xff01; 目录 背景知识 命名空间(namespace) 为何引入namespace namespace的定义 namespace的使用 背景知识 C的起源要追溯到1979年&#xff0…

(2024|Nature Medicine,生物医学 AI,BiomedGPT)面向多种生物医学任务的通用视觉-语言基础模型

BiomedGPT: A generalist vision–language foundation model for diverse biomedical tasks 目录 1. 摘要 2. 引言 3. 相关研究 3.1 基础模型与通用生物医学 AI 3.2 生物医学 AI 的局限性 3.3 BiomedGPT 的创新点 4. 方法 4.1 架构及表示 4.1.1 模型架构选择 4.1.2 …