UserServiceMockitoTest
测试类package com.example.demo;/** *Author:hw0089751 *Date:2025/10/9 */ import com.example.demo.mockitodemo.UserDTO; import com.example.demo.mockitodemo.UserService; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.web.client.RestTemplate; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; /** * 一、ExtendWith注解 * ExtendWith 注解是 JUnit 5 中的一个扩展机制用于为测试类或测试方法提供扩展功能。 * 它的主要作用是注册一个或多个扩展Extension这些扩展可以在测试的生命周期中 执行额外的逻辑例如初始化、清理、拦截测试执行等。 * * 常见扩展 * 1.MockitoExtension * 提供 Mockito 的支持例如自动创建 Mock 对象。 * 2.SpringExtension * 集成 Spring 的测试功能例如加载 Spring 上下文。 * 3.TempDirectory * 提供临时目录支持用于文件操作测试。 * * 二、Mock注解 * Mock 注解是 Mockito 框架中的一个核心注解用于创建一个模拟对象Mock Object。 它的主要作用是替代真实对象 * 用于测试代码中的依赖关系从而隔离测试逻辑避免依赖外部系统或复杂的对象。 * * 作用 * 1.创建 Mock 对象 * Mock 会创建一个模拟对象模拟对象可以替代真实对象的行为。 * 通过 Mockito.when() 方法可以定义模拟对象的行为。 * 2.隔离测试 * 使用 Mock 可以避免测试依赖真实对象从而专注于测试目标代码的逻辑。 * 3.简化测试代码 * 通过注解方式创建 Mock 对象避免手动调用 Mockito.mock() 方法。 * 4.结合 InjectMocks 使用 * Mock 创建的模拟对象可以自动注入到被测试的类中简化依赖注入。 * * 三、Mock注解 * InjectMocks 是 Mockito 框架中的一个注解用于自动将标记为 Mock 或 Spy 的模拟对象Mock 或 Spy注入到被测试的类中。 * 它的主要作用是简化依赖注入过程避免手动创建和设置依赖。 * * 作用 * 1.自动注入依赖 * InjectMocks 会将标记为 Mock 或 Spy 的对象注入到被测试类的字段中。 * 支持构造函数注入、字段注入和 setter 方法注入。 * * 2.简化测试代码 * 避免手动创建被测试类的实例以及注入依赖提升代码可读性。 * * 3.结合 Mock 使用 * InjectMocks 通常与 Mock 一起使用Mock 创建的模拟对象会自动注入到被测试类中。 * */ // 启用Mockito扩展 ExtendWith(MockitoExtension.class) public class UserServiceMockitoTest { Mock private RestTemplate restTemplate; // 模拟RestTemplate依赖被测试的类内部依赖的类 InjectMocks private UserService userService; // 将模拟对象注入被测类被测试的类 Test void createUser_shouldReturnUserIdOnSuccess() { // 准备测试数据 UserDTO userDTO new UserDTO(testmail.com, Test User); // 配置模拟行为当调用postForObject方法时返回预设响应 String mockedResponse user-id-123; // when(restTemplate.postForObject( // eq(http://localhost:19001/users), // 使用实际URL // any(UserDTO.class), // 使用更宽松的匹配 // eq(String.class)) // 匹配响应类型 // ).thenReturn(mockedResponse); // 不要换行换行影响执行结果 when(restTemplate.postForObject(anyString(), any(),eq(String.class))).thenReturn(mockedResponse); // 调用被测方法 String userId userService.createUser(userDTO); // 验证结果 assertEquals(user-id-123, userId); // 验证方法调用细节 verify(restTemplate, times(1)) .postForObject(eq(http://localhost:19001/users), same(userDTO), eq(String.class)); } Test void createUser_shouldHandleServerErrors() { UserDTO requestUser new UserDTO(failmail.com, null); // 配置模拟行为抛出特定异常 when(restTemplate.postForObject( anyString(), same(requestUser), eq(String.class) )).thenThrow(new RuntimeException(Internal server error)); // 验证异常抛出 Exception ex assertThrows(RuntimeException.class, () - { userService.createUser(requestUser); }); assertEquals(Internal server error, ex.getMessage()); // verify(restTemplate).postForObject( // contains(/users), // URL包含特定字符 // argThat(u - u. null), // 参数自定义断言 // eq(String.class) // ); } }被测试相关类package com.example.demo.mockitodemo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; /** * Author:hw0089751 * Date:2025/10/10 */ RestController public class UserController { Autowired private UserService userService; PostMapping(/getUser) public String createUser(RequestBody UserDTO user) { // 业务逻辑比如调用service return userService.createUser(user); } } package com.example.demo.mockitodemo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; /** * Author:hw0089751 * Date:2025/10/9 */ Service public class UserService { Autowired private RestTemplate restTemplate; private final String apiUrl http://localhost:19001/users; public String createUser(UserDTO userDto) { // POST请求创建用户 String result restTemplate.postForObject(apiUrl, userDto, String.class); return result; } } package com.example.demo.mockitodemo; /** * Author:hw0089751 * Date:2025/10/9 */ // 辅助数据传输类 public class UserDTO { private String email; private String name; public UserDTO(String email, String name) { this.email email; this.name name; } // getters省略 public String getEmail() { return email; } public void setEmail(String email) { this.email email; } public String getName() { return name; } public void setName(String name) { this.name name; } }

相关新闻

力扣 0645 错误的集合(Set Mismatch):哈希表与数学方法双解法实战解析

力扣 0645 错误的集合(Set Mismatch):哈希表与数学方法双解法实战解析

教程文档知识库 【免费下载链接】AlgoNote ⛽️「算法通关手册」:从零开始的「算法与数据结构」学习教程,200 道「算法面试热门题目」,1000 道「LeetCode 题目解析」,持续更新中! 项目地址: https://gitcod…

2026/10/9 1:41:09 阅读更多 →
TRAE 无法切换运行 conda 创建的环境:把 settings 改到 TaoToken 后排查 run 运行方式

TRAE 无法切换运行 conda 创建的环境:把 settings 改到 TaoToken 后排查 run 运行方式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 1:40:09 阅读更多 →
降AIGC黑科技揭秘!全网实测榜单与智能选型宝典:TaoToken统一Key接入实测

降AIGC黑科技揭秘!全网实测榜单与智能选型宝典:TaoToken统一Key接入实测

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 1:40:08 阅读更多 →

最新新闻

浏览器扩展端侧AI推理:WebGPU+ONNX Runtime实战架构

浏览器扩展端侧AI推理:WebGPU+ONNX Runtime实战架构

1. 这不是“把模型塞进浏览器”那么简单:端侧AI在扩展环境里的真实战场“现代浏览器扩展环境下的端侧 AI 推理系统架构与工程实现规范”——这个标题里没有一个词是虚的,每个字都踩在当下前端工程最硬的几块石头上。我从去年开始带团队落地三个真实商用级…

2026/10/9 7:00:47 阅读更多 →
MiMo-V2.6:面向自我改进的工业级强化学习架构

MiMo-V2.6:面向自我改进的工业级强化学习架构

1. 这不是一篇“读论文就完事”的笔记,而是一次对强化学习边界的实地勘探“MiMo-V2.6 - Scaling Reinforcement Learning Towards Self-Improvement”这个标题里藏着三个关键信号:MiMo(Multi-Model,多模型协同)、V2.6&…

2026/10/9 7:00:47 阅读更多 →
Vue过滤器指南:原理、使用场景及面试避坑

Vue过滤器指南:原理、使用场景及面试避坑

最近这道面试题出现的频率不低,尤其面试 Vue 相关岗位时,冷不丁就会被问到:“说说 Vue 过滤器是什么?有哪些使用场景?”很多人第一反应是“用过”,但真让展开讲讲,又容易和计算属性、方法混在一…

2026/10/9 7:00:47 阅读更多 →
人工智能数学基础:梯度下降、优化器与正则化的核心原理与实战

人工智能数学基础:梯度下降、优化器与正则化的核心原理与实战

手头这本《人工智能数学基础》翻到第十八章的时候,我其实松了一口气——前面十几章的线性代数、微积分、概率论铺了那么多,总算开始收网了。这一章讲的内容,很多人可能会觉得“不就是优化算法和正则化嘛”,但真等到训练模型训练不…

2026/10/9 7:00:47 阅读更多 →
WorkBuddy实战:搭建Excel VBA模板母版-副本自动同步系统

WorkBuddy实战:搭建Excel VBA模板母版-副本自动同步系统

我把手头几张各写各的VBA模板文档,用WorkBuddy理成了母版-副本自动同步的总控台。前几周我一直在维护一套Excel进销存模板,里面有报价单、对账单、领料单,每张表里都塞了一段VBA逻辑,逻辑还互相抄。最崩溃的一次是改完报价单的客户…

2026/10/9 7:00:47 阅读更多 →
C语言数据类型与变量:内存机制、指针结构与实战避坑指南

C语言数据类型与变量:内存机制、指针结构与实战避坑指南

C语言的数据类型和变量,看上去是每本教材开篇就讲的基础,但我在实际带项目、看别人代码、甚至帮人排查问题的时候发现,很多人恰恰是栽在这些“基础”上。指针用得晕、结构体定义不明白、类型转换出bug、变量作用域一锅粥——这些问题十有八九…

2026/10/9 6:59:46 阅读更多 →

日新闻

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API这个话题,隔三差五就会在群里被翻出来讨论一次。上周还有个同事线上处理一个订单超时问题,排查到最后发现是ZonedDateTime序列化后时区丢了,用户在下单当天晚上看到的时间整整差了8个小时。这类问题几乎每个做Java开发的人都遇到过…

2026/10/9 0:00:49 阅读更多 →
EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

前几个月我手头有好几台机器需要互相访问:办公室台式机、家里 NAS、还有一台云主机。如果只是偶尔传个文件倒还好,问题是工作场景经常要在几处环境之间来回切换,每次都先登录跳板机再层层代理,实在折腾。我先后试过端口映射、自建…

2026/10/9 0:00:49 阅读更多 →
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及,但真正动手搭过一套能跑起来的 Agent 系统的人都知道,从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地,从最初用现成框架拼装&…

2026/10/9 0:01:50 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:40 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 10:10:36 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 21:13:17 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 6:17:20 阅读更多 →