使用 Mockito 进行 Service 层单元测试:详细教程

使用 mockito 进行 service 层单元测试:详细教程

本文旨在帮助开发者掌握使用 Mockito 框架对 Spring Boot 应用中的 Service 层进行单元测试的方法。通过详细的代码示例和步骤,我们将演示如何有效地 Mock 依赖的 DAO 和 Service,从而隔离被测 Service,保证测试的准确性和可靠性。

在编写单元测试时,特别是针对 Service 层,经常需要模拟(Mock)其依赖的其他 Service 或 DAO(Data Access Object)的行为。这允许你专注于测试特定 Service 的逻辑,而无需担心依赖项的真实实现是否正确或可用。Mockito 是一个流行的 Java Mocking 框架,可以方便地创建和配置 Mock 对象。

以下是一个使用 Mockito 进行 Service 层单元测试的示例,并解释了常见的错误和解决方法。

1. 准备工作

首先,确保你的项目中引入了必要的依赖:

    org.springframework.boot    spring-boot-starter-test    test    org.mockito    mockito-core    test

2. 示例 Service 和 DAO

假设我们有以下 Service 和 DAO:

// ScoreDAO.javapublic interface ScoreDAO {    int insert(ScoreModel score);}// SubjectService.javapublic interface SubjectService {    SubjectModel getNameSubject(RequestModel request, String nameStudent);}// ExamServiceImpl.java@Servicepublic class ExamServiceImpl implements ExamService {    @Autowired    private SubjectService subjectService;    @Autowired    private ScoreDAO scoreDAO;    @Autowired    private TeacherDAO teacherDAO;    @Autowired    private StudentDAO studentDAO;    @Override    public ResponseModel insertScore(RequestModel request) throws IOException {        List teacher = teacherDAO.getNameList(request);        List student = studentDAO.findStudentList(teacher.get(0).getName(), request.getStudentScore);        String nameStudent = student.get(0).getFirstName() + student.get(0).getLastName();        SubjectModel subject = subjectService.getNameSubject(request, nameStudent);        ScoreModel score = new ScoreModel();        score.setStudentName(request.getStudentName);        score.setScore(request.getStudentScore);        score.setSubject(subject.getName);        int result = scoreDAO.insert(score);        return new ResponseModel(result); // Changed to return ResponseModel    }}

3. 编写单元测试

青柚面试 青柚面试

简单好用的日语面试辅助工具

青柚面试 57 查看详情 青柚面试

import org.junit.jupiter.api.Test;import org.mockito.InjectMocks;import org.mockito.Mock;import org.mockito.Mockito;import org.springframework.boot.test.context.SpringBootTest;import java.io.IOException;import java.util.ArrayList;import java.util.List;import static org.junit.jupiter.api.Assertions.assertEquals;import static org.mockito.ArgumentMatchers.any;import static org.mockito.ArgumentMatchers.anyString;import static org.mockito.Mockito.when;@SpringBootTestpublic class ExamServiceImplTest {    @Mock    private ScoreDAO scoreDAO;    @Mock    private SubjectService subjectService;    @Mock    private TeacherDAO teacherDAO;    @Mock    private StudentDAO studentDAO;    @InjectMocks    private ExamServiceImpl examService;    @Test    void insertScoreTest() throws IOException {        // 1. 定义 Mock 对象的行为        SubjectModel resFromSubject = new SubjectModel();        resFromSubject.setName("Math");        TeacherModel resTeacher = new TeacherModel();        resTeacher.setName("test Teacher");        List teacherList = new ArrayList();        teacherList.add(resTeacher);        StudentModel studentData = new StudentModel();        studentData.setFirstName("firstname");        studentData.setLastName("lastname");        List studentList = new ArrayList();        studentList.add(studentData);        when(teacherDAO.getNameList(any(RequestModel.class))).thenReturn(teacherList);        when(studentDAO.findStudentList(anyString(), anyString())).thenReturn(studentList);        when(subjectService.getNameSubject(any(RequestModel.class), anyString())).thenReturn(resFromSubject);        when(scoreDAO.insert(any(ScoreModel.class))).thenReturn(1);        // 2. 执行被测方法        ResponseModel resultTest = examService.insertScore(new RequestModel());        // 3. 验证结果        assertEquals(1, resultTest.getResult());    }}

关键点解释:

@SpringBootTest: 启动完整的 Spring 上下文,允许注入 Mock 对象和真实的 Service。@Mock: 用于创建 Mock 对象。 @MockBean 在 Spring 上下文中替换现有的 Bean,而 @Mock 只是创建一个 Mock 对象,需要手动注入到被测类中。推荐使用 @Mock 和 @InjectMocks,可以更清晰地控制依赖关系。@InjectMocks: 自动将带有 @Mock 注解的 Mock 对象注入到被测 Service 中。Mockito.when(…).thenReturn(…): 定义 Mock 对象的行为。 当调用 teacherDAO.getNameList(any(RequestModel.class)) 时,返回预定义的 teacherList。 any() 和 anyString() 是 Mockito 提供的参数匹配器,用于匹配任何类型的参数。examService.insertScore(new RequestModel()): 执行被测方法。assertEquals(1, resultTest.getResult()): 断言结果是否符合预期。

常见问题和解决方法:

Mock 对象未生效:

原因: 可能忘记使用 @InjectMocks 将 Mock 对象注入到被测 Service 中。解决方法: 确保正确使用 @Mock 和 @InjectMocks 注解。

NullPointerException:

原因: Mock 对象的方法没有定义行为,导致返回 null。解决方法: 使用 Mockito.when(…).thenReturn(…) 定义 Mock 对象的行为。 确保所有被调用的 Mock 对象的方法都有对应的定义。

参数匹配错误:

原因: 传递给 Mock 对象方法的参数与定义的参数不匹配。解决方法: 使用 Mockito 提供的参数匹配器,例如 any(), anyString(), eq() 等。

总结:

使用 Mockito 可以有效地隔离 Service 层的依赖,编写可重复、可靠的单元测试。 通过 @Mock 创建 Mock 对象,使用 @InjectMocks 注入依赖,并使用 Mockito.when(…).thenReturn(…) 定义 Mock 对象的行为,可以轻松地模拟各种场景,验证 Service 层的业务逻辑。 记住,良好的单元测试覆盖率是保证代码质量的重要手段。

以上就是使用 Mockito 进行 Service 层单元测试:详细教程的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/292404.html

赞 (0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
我国网民规模突破11亿
上一篇 2025年11月4日 21:10:20
俄罗斯手机版浏览器入口 俄罗斯浏览器网站手机登录官方链接
下一篇 2025年11月4日 21:10:24

相关推荐

  • 输入数值范围校验:Java实现用户输入在30到70之间的程序

    输入数值范围校验:Java实现用户输入在30到70之间的程序输入数值范围校验:Java实现用户输入在30到70之间的程序输入数值范围校验:Java实现用户输入在30到70之间的程序输入数值范围校验:Java实现用户输入在30到70之间的程序

    本文将指导你如何编写一个Java程序,该程序接收用户输入的整数,并验证该整数是否在30到70的范围内。如果输入超出范围,程序将提示用户重新输入,直到输入有效为止。文章将详细讲解代码实现,并提供注意事项,帮助你理解循环控制和输入处理的关键点。 实现用户输入范围校验的Java程序 本教程将引导你完成一个…

    2026年9月30日 • 用户投稿
    100
  • 乘坐载具会走光! 玩家发现《无主之地4》另类bug

    乘坐载具会走光! 玩家发现《无主之地4》另类bug乘坐载具会走光! 玩家发现《无主之地4》另类bug乘坐载具会走光! 玩家发现《无主之地4》另类bug乘坐载具会走光! 玩家发现《无主之地4》另类bug

    尽管《无主之地4》在首发阶段展现出亮眼的表现,战斗系统也备受好评,但游戏仍暴露出一些设计上的短板。比如操作繁琐的ui界面和遍布地图的空气墙问题频频出现。这些虽是较为严重的设计缺陷,不过游戏中也不乏一些令人忍俊不禁的小型漏洞。最近在玩家圈中引发热议的,便是角色“裤子莫名消失”的离奇bug。 Reddi…

    2026年9月30日 • 用户投稿
    100
  • 在 Cucumber 中跨 Scenario 共享变量:方法与最佳实践

    在 Cucumber 中跨 Scenario 共享变量:方法与最佳实践在 Cucumber 中跨 Scenario 共享变量:方法与最佳实践在 Cucumber 中跨 Scenario 共享变量:方法与最佳实践在 Cucumber 中跨 Scenario 共享变量:方法与最佳实践

    “本文探讨了在 Cucumber 测试中跨不同 Scenario 共享变量的方法,并着重强调了最佳实践。虽然可以通过全局变量实现跨 Scenario 的数据传递,但更推荐使用 Background 来管理测试依赖,确保 Scenario 的独立性和可维护性。本文将详细介绍这两种方法,并分析各自的优缺…

    2026年9月30日 • 用户投稿
    000
  • 使用 HashMap 优化嵌套循环:Java 对象数组转换

    使用 HashMap 优化嵌套循环:Java 对象数组转换使用 HashMap 优化嵌套循环:Java 对象数组转换使用 HashMap 优化嵌套循环:Java 对象数组转换使用 HashMap 优化嵌套循环:Java 对象数组转换

    本文旨在提供一种使用 HashMap 优化 Java 中嵌套循环的有效方法,特别是当循环涉及对象数组并进行相等性检查时。通过将内部循环转换为 HashMap 查询,可以显著降低时间复杂度,提高代码性能。本文将提供详细的步骤和示例代码,帮助读者理解和应用这种优化技巧。 在处理包含嵌套循环的 Java …

    2026年9月30日 • 用户投稿
    100
  • Java代码无报错但无法运行:二进制转十进制的常见陷阱与解决方案

    本文旨在帮助Java初学者解决代码无报错但无法正常运行的问题,特别是针对二进制转换为十进制的场景。通过分析常见错误原因,例如误用取余运算符,提供详细的调试方法和修正后的代码示例,帮助读者理解并掌握正确的二进制转换逻辑,避免程序进入死循环,确保代码的正确执行。 在Java编程中,有时会遇到代码没有报错…

    2026年9月30日
    100
  • java代码如何用Lambda表达式简化代码 java代码函数式编程的应用教程​

    java代码如何用Lambda表达式简化代码 java代码函数式编程的应用教程​java代码如何用Lambda表达式简化代码 java代码函数式编程的应用教程​java代码如何用Lambda表达式简化代码 java代码函数式编程的应用教程​java代码如何用Lambda表达式简化代码 java代码函数式编程的应用教程​

    Lambda表达式的基本语法是(参数) -> 表达式或代码块,用于简化匿名内部类的编写,尤其在集合操作中通过Stream API实现filter、map等操作,显著提升代码简洁性与可读性。 Lambda表达式在Java里,说白了,就是让代码更简洁,特别是处理集合数据的时候。它能把原本需要好几行…

    2026年9月30日 • 用户投稿
    100
  • 动态加载 Spring Beans 的最佳实践

    动态加载 Spring Beans 的最佳实践动态加载 Spring Beans 的最佳实践动态加载 Spring Beans 的最佳实践动态加载 Spring Beans 的最佳实践

    本文介绍了如何在 Spring 应用程序中基于环境动态加载不同的 Bean 实现。通过使用 @Conditional 注解和手动配置 Bean,可以根据特定条件选择性地加载 DoThingService 或 NoopService,从而避免了 Bean 冲突问题,并简化了单元测试。 在 Spring…

    2026年9月30日 • 用户投稿
    200
  • Java程序流程控制之循环与分支_Java实现程序逻辑的基础语句

    Java程序流程控制之循环与分支_Java实现程序逻辑的基础语句Java程序流程控制之循环与分支_Java实现程序逻辑的基础语句Java程序流程控制之循环与分支_Java实现程序逻辑的基础语句Java程序流程控制之循环与分支_Java实现程序逻辑的基础语句

    Java中的循环和分支是程序实现逻辑控制的核心。分支语句(如if、if-else、switch)根据条件选择执行路径,其中if处理复杂条件,switch适用于单一变量的多值判断;循环语句(如for、while、do-while)实现重复执行,for用于已知次数或遍历,while在条件满足时执行(可能…

    2026年9月30日 • 用户投稿
    100
  • VSCode如何实现云开发集成 VSCode连接AWS/Azure的配置指南

    VSCode如何实现云开发集成 VSCode连接AWS/Azure的配置指南VSCode如何实现云开发集成 VSCode连接AWS/Azure的配置指南VSCode如何实现云开发集成 VSCode连接AWS/Azure的配置指南VSCode如何实现云开发集成 VSCode连接AWS/Azure的配置指南

    要实现vscode云开发集成,必须安装云厂商提供的扩展并配置cli工具。1. 安装扩展:aws使用“aws toolkit”,azure安装“azure account”和“azure resources”扩展,以获得图形化管理界面。2. 配置认证信息:aws需设置access key id和sec…

    2026年9月30日 • 用户投稿
    700
  • java怎样使用JVM参数配置运行环境 java虚拟机调优的入门技巧

    java怎样使用JVM参数配置运行环境 java虚拟机调优的入门技巧java怎样使用JVM参数配置运行环境 java虚拟机调优的入门技巧java怎样使用JVM参数配置运行环境 java虚拟机调优的入门技巧java怎样使用JVM参数配置运行环境 java虚拟机调优的入门技巧

    配置JVM运行环境需通过命令行参数设置内存、GC策略等,如-Xms512m -Xmx2g -XX:+UseG1GC,以优化资源利用率、响应速度与稳定性,避免OOM,提升应用性能。 配置Java虚拟机(JVM)运行环境以及进行初步调优,核心在于通过命令行参数来指导JVM如何分配和管理资源,以及选择合适…

    2026年9月30日 • 用户投稿
    100
  • 我的世界谜之炖菜怎么制作 谜之炖菜合成方法介绍

    我的世界谜之炖菜怎么制作 谜之炖菜合成方法介绍我的世界谜之炖菜怎么制作 谜之炖菜合成方法介绍我的世界谜之炖菜怎么制作 谜之炖菜合成方法介绍我的世界谜之炖菜怎么制作 谜之炖菜合成方法介绍

    我的世界谜之炖菜可通过红色蘑菇、棕色蘑菇、碗和任意小型花合成,也能通过多种途径获取,食用后恢复饥饿值和饱和度,还会获得对应花的状态效果,以下是详细的物品介绍。 我的世界谜之炖菜合成方法和特性介绍如下: 一、合成方法 需准备红色蘑菇、棕色蘑菇、碗和任意小型花,将这些材料在工作台合成即可获得谜之炖菜。 …

    2026年9月30日 • 用户投稿
    300
  • 大厂面试必考之Java集合原理_Java集合框架的底层实现与应用

    大厂面试必考之Java集合原理_Java集合框架的底层实现与应用大厂面试必考之Java集合原理_Java集合框架的底层实现与应用大厂面试必考之Java集合原理_Java集合框架的底层实现与应用大厂面试必考之Java集合原理_Java集合框架的底层实现与应用

    Java集合框架的核心是List、Set、Map三大接口。List有序可重复,常用实现ArrayList(数组实现,查询快)和LinkedList(链表实现,增删快);Set元素唯一,HashSet基于哈希表实现(查找快),TreeSet基于红黑树(有序);Map存储键值对,键唯一,HashMap(…

    2026年9月30日 • 用户投稿
    100
  • 将 XML Bean 定义迁移到 @Configuration 注解类

    将 XML Bean 定义迁移到 @Configuration 注解类 本文将指导您如何将 Spring 应用中基于 XML 的 JMS Bean 定义迁移到使用 @Configuration 注解的 Java 类中。通过示例,我们将展示如何使用 @Bean 注解创建 JmsTemplate 和 J…

    2026年9月30日
    100
  • Java中利用正则表达式实现字符串特定单词的忽略大小写替换

    本教程旨在解决如何在字符串中高效地将特定单词的所有大小写变体统一转换为指定大小写形式的问题。通过引入正则表达式的“大小写不敏感”匹配模式,我们能够避免为每种变体编写单独的替换规则,从而实现简洁、灵活且强大的字符串处理,显著提升代码效率和可维护性。 传统替换方法的局限性 在字符串处理中,我们经常会遇到…

    2026年9月30日
    100
  • 提升代码质量之Java枚举的正确用法_Java枚举类型的实战技巧

    提升代码质量之Java枚举的正确用法_Java枚举类型的实战技巧提升代码质量之Java枚举的正确用法_Java枚举类型的实战技巧提升代码质量之Java枚举的正确用法_Java枚举类型的实战技巧提升代码质量之Java枚举的正确用法_Java枚举类型的实战技巧

    Java枚举通过封装数据和行为,提供类型安全、避免魔法值,提升代码可读性与可维护性,如订单状态枚举可携带状态码、描述及处理逻辑,并支持策略模式,取代冗长if-else,实现清晰多态。 Java枚举,远不止是简单的常量集合,它是提升代码健壮性、可读性和可维护性的利器。通过它,我们能将一组固定的、有限的…

    2026年9月30日 • 用户投稿
    200
  • R包降级也不全是那么简单

    R包降级也不全是那么简单R包降级也不全是那么简单R包降级也不全是那么简单R包降级也不全是那么简单

    如果你是windows用户,可能会遇到make缺失的错误,如下图所示: 尽管我已经多年未使用Windows,但解决这个问题其实非常简单,只需通过谷歌搜索即可找到答案: 实际上,这是由于rtools缺失导致的问题。Windows用户只需下载适合的rtools版本并安装即可解决。 下载并安装Rtools…

    2026年9月30日 • 用户投稿
    200
  • 重装系统后网络适配器怎么不见了?没有网络适配器解决方法

    重装系统后网络适配器怎么不见了?没有网络适配器解决方法重装系统后网络适配器怎么不见了?没有网络适配器解决方法重装系统后网络适配器怎么不见了?没有网络适配器解决方法重装系统后网络适配器怎么不见了?没有网络适配器解决方法

    在使用电脑时,我们常常需要通过网络适配器来配置网络相关设置。然而,有些用户在重装windows 10系统后,发现设备管理器中找不到网络适配器了。这该如何解决呢?下面我们就来详细探讨重装系统后网络适配器消失的原因及应对方法。 为什么重装系统后网络适配器不见了? Win10系统中网络适配器缺失,可能是由…

    2026年9月30日 • 用户投稿
    200
  • sublime如何实现AI代码补全 sublime集成Copilot的替代方案

    sublime如何实现AI代码补全 sublime集成Copilot的替代方案sublime如何实现AI代码补全 sublime集成Copilot的替代方案sublime如何实现AI代码补全 sublime集成Copilot的替代方案sublime如何实现AI代码补全 sublime集成Copilot的替代方案

    sublime text需通过插件实现ai代码补全,因其本身不集成ai功能,但可通过package control安装如tabnine等插件来实现;2. tabnine支持多语言和本地补全,保护隐私且无需订阅,但智能性略逊于copilot;3. 可通过编写自定义插件调用openai api实现补全,…

    2026年9月29日 • 用户投稿
    200
  • sublime如何实现代码自动补全 sublime代码自动补全功能的配置方法

    sublime如何实现代码自动补全 sublime代码自动补全功能的配置方法sublime如何实现代码自动补全 sublime代码自动补全功能的配置方法sublime如何实现代码自动补全 sublime代码自动补全功能的配置方法sublime如何实现代码自动补全 sublime代码自动补全功能的配置方法

    sublime text实现代码自动补全的核心是内置匹配、自定义片段和第三方插件的组合;2. 开箱即用的词汇匹配需结合package control安装插件如lsp、all autocomplete、emmet等以实现智能补全;3. 补全失效常见原因为语法模式错误、插件冲突、大型项目性能问题或语言服…

    2026年9月29日 • 用户投稿
    500
  • PHP与SQL实现高效预约时间冲突检测教程

    本教程旨在详细指导如何在php应用程序中,利用sql查询高效检测预约时间冲突。通过构建包含精确时间重叠逻辑的`count(*)`查询,能够准确判断新提交的预约请求是否与数据库中现有预约发生冲突。这有助于避免重复预订,确保预约系统的准确性、可靠性及用户体验。 引言:预约系统中的时间冲突挑战 在开发任何…

    2026年9月29日
    100

发表回复

登录后才能评论
关注微信