Mockito测试框架入门与使用

目录

    • Mockito
    • Mockito使用
      • Mockito依赖
      • Mockito常用注解
      • Mockito常用方法

Mockito

Mockito 是一个流行的 Java 单元测试框架,用于模拟(mock)对象以便进行单元测试。它可以帮助开发人员创建和管理模拟对象,以便在测试过程中替换那些不容易构造或获取的对象,从而达到测试被测代码的行为,而无需依赖于实际的外部系统或服务。

Mockito 的主要特点包括:

  1. 模拟对象:Mockito 允许创建模拟对象,这些模拟对象具有与真实对象相似的行为,但实际上只是虚拟的对象实例。通过模拟对象,可以模拟外部依赖、交互行为等,从而使测试更加独立和可控。

  2. 验证行为:Mockito 提供了丰富的 API 来验证模拟对象的交互行为,例如方法是否被调用、调用次数、参数匹配等。通过验证行为,可以确保被测代码按预期执行了与外部系统的交互。

  3. Stubbing 方法:Mockito 允许对模拟对象的方法进行 Stubbing,即定义当调用某个方法时应该返回的值。这样可以模拟不同的场景和条件,以覆盖多种测试情况。

  4. 灵活性:Mockito 提供了简洁且易于使用的 API,支持与 JUnit、TestNG 等测试框架集成。同时,它还提供了丰富的功能和扩展,可以满足各种测试场景的需求。

Mockito使用

Mockito依赖

SpringBoot默认的Mock框架是Mockito,和junit一样,只需要依赖spring-boot-starter-test就可以了

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope>
</dependency>

如果是单独添加依赖,那么添加下面依赖

 	<dependency><groupId>org.mockito</groupId><artifactId>mockito-core</artifactId><version>{mockito_version}</version></dependency><dependency><groupId>org.mockito</groupId><artifactId>mockito-junit-jupiter</artifactId><version>{mockito_version}</version></dependency>

mockito-core:Mockito 核心依赖,提供了 Mockito 框架的核心功能和 API。

mockito-junit-jupiter:Mockito 与 JUnit Jupiter 的集成依赖,用于在 JUnit 5 环境下使用 Mockito 进行单元测试。

如果需要使用内联Mocks,那么还需要添加下面这个依赖

mockito-inline:Mockito 的内联依赖,用于支持内联(inline)Mocks 的创建和使用。

Mockito常用注解

@RunWith

@RunWith注解用于在JUnit测试中指定运行器(Runner),常用的有以下两种

  1. @RunWith(MockitoJUnitRunner.class)
    • @RunWith(MockitoJUnitRunner.class) 是Mockito框架提供的JUnit运行器,用于运行使用Mockito进行单元测试的类。
    • 当使用 @RunWith(MockitoJUnitRunner.class) 注解一个测试类时,Mockito会自动初始化这个类中使用 @Mock@InjectMocks 等注解创建的模拟对象。
    • 这样可以简化测试类的设置过程,使得在测试中可以直接使用模拟对象而不需要手动初始化。
@RunWith(MockitoJUnitRunner.class)
public class SomeTestClass {@Mockprivate SomeService someService;// Test methods using mock objects
}
  1. @RunWith(SpringRunner.class)
    • @RunWith(SpringRunner.class) 是Spring Framework提供的JUnit运行器,用于运行基于Spring的集成测试。
    • 当使用 @RunWith(SpringRunner.class) 注解一个测试类时,Spring会加载应用程序上下文,并可以通过@Autowired等注解注入Spring管理的Bean。
    • 这样可以进行更真实的集成测试,包括与数据库、外部服务的交互等。
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringIntegrationTest {@Autowiredprivate SomeService someService;// Integration test methods using Spring context
}

注:如果是在Spring Boot项目中,使用了@SpringBootTest注解,就不需要再额外使用@RunWith注解了。因为在Spring Boot中,@SpringBootTest注解用于创建一个完整的应用程序上下文,这样你就可以在测试中使用所有的Spring Beans和自动配置。这个注解本身就包含了@RunWith(SpringRunner.class)的功能,因此你不需要显式地添加@RunWith注解。

@Test
标记测试方法,被 @Test 注解标记的方法会被 JUnit 的运行器执行,作为测试方法进行测试。

@MockBean

模拟Spring Boot应用程序中Spring上下文的对象,@MockBean是Spring Boot测试框架的一部分(属于spring-boot-test包),@MockBean注解的类将替代Spring容器中同类型的类。如果同类型的类不存在,@MockBean会自动定义并添加它。对于不是bean的依赖,@MockBean会将它模拟成bean并与存在的依赖一起添加到上下文中。在Spring Boot的测试类中,@MockBean通常与@SpringBootTest和@AutoConfigureMockMvc等注解一起使用。

在Spring Boot的测试类中,通常更倾向于使用@MockBean来模拟对象,因为它与Spring Boot的测试框架有更好的集成。

@Mock

创建一个模拟对象,并注入到测试类中。通常和 @InjectMocks 注解一起使用,用于为测试类中的被测对象注入模拟对象。当你使用 @Mock 注解一个对象时,Mockito 会为你创建一个该对象的模拟实例。这个模拟实例的行为(即方法的返回值和它们被调用的方式)可以被精确地控制和验证。默认情况下,模拟对象上的所有方法调用都会返回 null(对于引用类型)或默认值(对于原始类型)。你可以使用 when(…).thenReturn(…)、when(…).thenThrow(…) 等 Mockito 方法来定义模拟对象的行为。

@Spy
用于创建一个部分模拟对象,与@Mock不同,@Spy创建的是一个实际对象的代理,并且允许你选择性地模拟对象中的某些方法。默认情况下,所有未被特别模拟的方法都会调用实际对象的方法,
通常与doReturn/doThrow等方法结合使用。

@Captor
用于捕获方法参数,以便验证方法调用参数是否正确。

@InjectMocks

注入被测对象,并自动将 @Mock 和 @Spy 标注的对象注入到被测对象中。

public class SomeTestClass {@Mockprivate SomeService someService;@InjectMocksprivate SomeController someController;}

@Before 和 @After
JUnit 提供的注解,在每个测试方法执行之前和之后分别执行一段代码。通常用于设置测试的前置条件或进行资源的清理工作。

public class SomeTestClass {@Beforepublic void setUp() {// Set up test data or initialize resources}@Afterpublic void tearDown() {// Clean up resources}@Testpublic void testSomeMethod() {// Test method}
}

Mockito常用方法

Mockito.when()

Mockito.when() 是 Mockito 框架中的一个方法,用于设置模拟对象的方法调用行为。它通常与 thenReturn()、thenThrow() 或 thenAnswer() 方法一起使用。

Mockito.when(mock.methodCall()).thenReturn(value) 的语法表示当模拟对象的 methodCall() 方法被调用时,应该返回指定的 value 值。

下面是 Mockito.when() 方法的一些常见用法:

  1. 返回固定值:

使用thenReturn返回一个固定值,如果返回多个值,使用逗号分隔

// 当 getUserById() 方法被调用时,返回一个预先定义的 User 对象
Mockito.when(userServiceMock.getUserById(1)).thenReturn(new User("Alice"));// 第一次调用 getUserById() 返回 Alice,第二次调用返回 Bob
Mockito.when(userServiceMock.getUserById(1)).thenReturn(new User("Alice")).thenReturn(new User("Bob"));
  1. 抛出异常

使用thenThrow可以抛出一个指定的异常

Mockito.when(userServiceMock.saveUser(null)).thenThrow(new IllegalArgumentException("Invalid parameter"));
  1. 使用 Answer 接口自定义行为

使用thenAnswer方法,传入Answer接口的实现类,就可以实现自定义返回

// 根据输入参数计算结果并返回
Mockito.when(calculatorMock.calculate(Mockito.anyInt(), Mockito.anyInt())).thenAnswer(invocation -> {int a = invocation.getArgument(0);int b = invocation.getArgument(1);return a + b;
});

Mockito.mock(Class classToMock)

用于创建一个指定类的模拟对象

Mockito.doReturn()

Mockito.doReturn() 用于设置模拟对象方法的返回值。与 Mockito.when().thenReturn() 方法类似,Mockito.doReturn() 也用于模拟方法调用时的返回结果,但在某些特定情况下会更加灵活和有效。

以下是 Mockito.doReturn() 方法的一些常见用法:

  1. 设置模拟对象方法的返回值:
// 使用 doReturn() 设置 getUserById() 方法的返回值
Mockito.doReturn(new User("Alice")).when(userServiceMock).getUserById(1);
  1. 处理 void 方法的行为:
// 设置 delete() 方法为无返回值时的行为
Mockito.doNothing().when(userServiceMock).deleteUser(1);// 设置 void 方法抛出异常时的行为
Mockito.doThrow(new RuntimeException("Unable to delete user")).when(userServiceMock).deleteUser(2);

Mockito.verify():

Mockito.verify() 用于验证模拟对象的方法是否被调用以及调用的次数。它通常与 times()、atLeastOnce()、never() 等方法一起使用。

Mockito.verify(mock, times(n)).methodCall() 的语法表示验证模拟对象的 methodCall() 方法被调用了 n 次。

以下是 Mockito.verify() 方法的一些常见用法:

  1. 验证方法是否被调用:

verify(mock): 验证模拟对象的方法至少被调用了一次。这是 verify 的默认行为。

Mockito.verify(userServiceMock).getUserById(1);
  1. 验证方法调用次数:

verify(mock, times(n)): 验证模拟对象的方法被调用了指定次数。

// 验证 getUserById() 方法被调用了两次
Mockito.verify(userServiceMock, times(2)).getUserById(1);// 验证 saveUser() 方法至少被调用了一次
Mockito.verify(userServiceMock, atLeastOnce()).saveUser(Mockito.any(User.class));// 验证 deleteUser() 方法从未被调用
Mockito.verify(userServiceMock, never()).deleteUser(2);

Mockito.any(Class type)

Mockito.any(Class type) 用于创建一个匹配任意指定类型的参数的匹配器。在设置模拟对象方法的行为时,我们经常会使用 Mockito.any() 来匹配任意参数。

下面是 Mockito.any() 方法的一些常见用法:

// 当 saveUser() 方法的参数为任意对象,都返回 true
Mockito.when(userServiceMock.saveUser(Mockito.any())).thenReturn(true);// 当 saveUser() 方法的参数为任意 User 对象时,都返回 true
Mockito.when(userServiceMock.saveUser(Mockito.any(User.class))).thenReturn(true);// 当 calculate() 方法的两个参数为任意整数时,返回固定值 10
Mockito.when(calculatorMock.calculate(Mockito.anyInt(), Mockit.anyInt())).thenReturn(10);

Mockito.reset
Mockito.reset(mock):重置模拟对象的状态,清除之前的交互和验证。

Mockito.reset(userServiceMock);

Mockito.eq()

Mockito.eq() 用于创建一个匹配特定参数值的匹配器。当你想在模拟对象的方法调用中匹配一个特定的参数时,你可以使用 eq。它通常与 when 和 verify 等方法一起使用。
下面是 Mockito.eq() 方法的一些常见用法:

  1. 匹配特定参数值:
// 当 getUserById() 方法的参数为 1 时返回特定的结果
Mockito.when(userServiceMock.getUserById(Mockito.eq(1))).thenReturn(new User("Alice"));// 当 calculate() 方法的两个参数为特定整数时返回固定值 10
Mockito.when(calculatorMock.calculate(Mockito.eq(2), Mockito.eq(3))).thenReturn(10);
  1. 验证方法调用时特定参数值:
// 验证 deleteUser() 方法被调用时传入的参数为特定整数
Mockito.verify(userServiceMock).deleteUser(Mockito.eq(1));

在这个例子中,verify 方法会确保 userServiceMock.deleteUser方法被调用过,并且传递的参数是 1。如果没有这样的调用发生,或者传递了不同的参数,那么验证将会失败。

需要注意的是,eq 只能用于精确匹配。如果你想匹配任何参数(不关心实际值),你应该使用 any()。

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

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

相关文章

mysql 分表实战

本文主要介绍基于range分区的相关 1、业务需求&#xff0c;每日160w数据&#xff0c;每月2000w;解决大表数据读写性能问题。 2、数据库mysql 8.0.34&#xff0c;默认innerDB;mysql自带的逻辑分表 3、分表的目的:解决大表性能差&#xff0c;小表缩小查询单位的特点(其实优化的精…

鼠标右键助手专业版 MouseBoost PRO for Mac v3.3.6中文破解

MouseBoost Pro mac版是一款简单实用的鼠标右键助手专业版&#xff0c;MouseBoost Pro for Mac只要轻点你的鼠标右键&#xff0c;就可以激活你想要的各种功能&#xff0c;让你的工作效率大幅度提高&#xff0c;非常好用。 软件下载&#xff1a;MouseBoost PRO for Mac v3.3.6中…

Gemma模型论文详解(附源码)

原文链接&#xff1a;Gemma模型论文详解&#xff08;附源码&#xff09; 1. 背景介绍 Gemma模型是在2023.2.21号Google新发布的大语言模型, Gemma复用了Gemini相同的技术(Gemini也是Google发布的多模态模型)&#xff0c;Gemma这次发布了了2B和7B两个版本的参数&#xff0c;不…

如何快速卸载windows电脑的一些软件?

本系列是一些电脑常规操作的普及&#xff0c;有需要借鉴即可 注&#xff1a;每个电脑都会有差异&#xff0c;参考即可。 其实大部分软件你删除桌面上的图标不等于删除&#xff0c;因为桌面上的那个图标就是一个简单的快捷方式而已。 在这里插入图片描述 那如何正确的卸载软件呢…

Android 广播的基本概念

一.广播简介 Broadcast是安卓四大组件之一。安卓为了方便进行系统级别的消息通知&#xff0c;引入了一套广播消息机制。打个比方&#xff0c;记得原来在上课的时候&#xff0c;每个班级的教室里都会装有一个喇叭&#xff0c;这些喇叭都是接入到学校的广播室的&#xff0c;一旦…

构建生物医学知识图谱from zero to hero (5):关系抽取

现在将尝试提取医学概念之间的关系。根据经验,关系提取比命名实体提取至少难一个数量级。如果不希望命名实体链接取得完美的结果,那么关系提取技术肯定会出现一些错误。 使用zero-shot关系提取器FewRel。虽然我不建议将此模型投入生产,但它足以进行简单的演示。该模型可在H…

(done) 什么是特征值和特征向量?如何求特征值的特征向量 ?如何判断一个矩阵能否相似对角化?

什么是齐次方程&#xff1f; https://blog.csdn.net/shimly123456/article/details/136198159 行列式和是否有解的关系&#xff1f; https://blog.csdn.net/shimly123456/article/details/136198215 特征值和特征向量 参考视频&#xff1a;https://www.bilibili.com/video/BV…

2240. 餐饮(最大流,拆点)

活动 - AcWing 奶牛们在吃饭方面十分挑剔。 每头奶牛都有自己喜欢的食物和饮料&#xff0c;并且不会食用其他不喜欢的食物和饮料。 农夫约翰为他的奶牛们做了美味的饭菜&#xff0c;但他忘了对照他们的喜好来检查菜单。 虽然他可能无法令所有奶牛满意&#xff0c;但他想给尽…

《Solidity 简易速速上手小册》第4章:智能合约的设计与开发(2024 最新版)

文章目录 4.1 合约结构和布局4.1.1 基础知识解析深入合约布局原则理解组织结构高效布局的重要性4.1.2 重点案例:构建一个在线商店合约案例 Demo:编写在线商店智能合约案例代码:OnlineStore.sol测试和验证拓展功能4.1.3 拓展案例 1:可升级的合约案例 Demo:创建可升级的智能…

安卓11-设置HDMI分辨率流程

安卓11中从设置-显示设置hdmi分辨率流程:framework层通过jni控制底层驱动实现&#xff0c;标准驱动模型 packages\apps\Settings\src\com\android\settings\display\HdmiSettings.javaprivate void updateResolution(final ITEM_CONTROL control, final int index) {showWaitin…

【主题广范|见刊快】2024年科技,绿色能源和可持续发展国际会议(ICTGESD 2024)

【主题广范|见刊快】2024年科技&#xff0c;绿色能源和可持续发展国际会议&#xff08;ICTGESD 2024&#xff09; 2024 International Conference on Technology, Green Energy, and Sustainable Development ⊙会议简介&#xff1a; 2024年科技&#xff0c;绿色能源和可持续发…

音视频技术-声反馈啸叫的产生与消除

目录 1.均衡调节: 2.移频法: 3.移相法: 4.比较法: 在扩音系统中,产生啸叫危害很大,一方面影响会议、演出等活动的正常进行,另一方面严重的啸叫会导致音响设备的损坏。 “啸叫”是“声反馈”的俗称,形成的机制复杂,消除的手段多样,专业调音师也对

Unity中URP实现水效果(水的深度)

文章目录 前言一、搭建预备场景1、新建一个面片&#xff0c;使其倾斜一个角度&#xff0c;来模拟水底和岸边的效果2、随便创建几个物体&#xff0c;作为与水面接触的物体3、再新建一个面片&#xff0c;作为水面 二、开始编写水体的Shader效果1、新建一个URP基础Shader2、把水体…

最优传输(Optimal Transport)

最优传输&#xff08;Optimal Transport&#xff09;是一种数学理论和计算方法&#xff0c;用于描述两个概率分布之间的距离或者对应关系。它的核心概念是如何以最佳方式将一组资源&#xff08;如质量、能量等&#xff09;从一个位置传输到另一个位置。 基本概念&#xff1a; …

Qt 5.12.12 如何使用 cmake

首先 我们需要 Qt6 的help 这里面有所有使用cmake的说明 Qt6 help 下载地址 : 链接: https://pan.baidu.com/s/1jhwdYLtFaAa7tq5Gly0gAQ?pwd6666 提取码: 6666 然后 通过 qt creator 安装help qt-creater打开 Tools -> options -> Help -> Documentation 选择 …

MongoDB聚合运算符:$avg

$avg运算符返回给定数值的平均值 $avg可用于以下阶段&#xff1a; $addFields阶段(从MongoDB 3.4开始可用)$bucket阶段$bucketAuto阶段$group阶段包含$expr表达式的$match阶段$project阶段$replaceRoot阶段(从MongoDB 3.4开始可用)$replaceWith阶段(从MongoDB 4.2开始可用)$s…

【Linux】设置线程名字prctl、pthread_setname_np

1、prctl 设置线程名字 1.1 说明 prctl 对线程和进程的操作,详见:https://man7.org/linux/man-pages/man2/prctl.2.html #include <sys/prctl.h>int prctl(int option , ... /* unsigned long arg2 , unsigned long arg3 , unsigned long arg4 , unsigned long arg5…

Java编程实战:构建医疗信息管理新平台

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

代码随想录算法训练营day25|216.组合总和III

216.组合总和III 题目链接/文章讲解&#xff1a;代码随想录 视频讲解&#xff1a;和组合问题有啥区别&#xff1f;回溯算法如何剪枝&#xff1f;| LeetCode&#xff1a;216.组合总和III_哔哩哔哩_bilibili 跟77题差不多&#xff0c;要搞清楚k确定了递归的深度 依旧用回溯三部…

cesium 高德路网数据加载到WGS-84坐标系,解决偏移问题

首先用到cesium.map.min.js 修改cesium.map.min.js中数据类型的瓦片路径 比如类型是img 搜索M.GCJ02ToWGS84&#xff0c;初步定位&#xff0c;确定是火星坐标系转wGS-84&#xff0c;然后修改 var S{img:"//webst{s}.is.autonavi.com/appmaptile?style6&x{x}&y{y…