当前位置: 首页 > article >正文

Java测试框架Mockito快速入门

Mockito结合TestNG快速入门

什么是Mockito

Mockito 是一个专门用于 Java 的强大测试框架,主要用来创建和管理模拟对象,辅助开发者进行单元测试,具有以下特点和功能:

  • 创建模拟对象:能通过简洁的语法创建类或接口的模拟版本,这些模拟对象可作为真实对象的替代品,在调试期间使用,帮助隔离外部依赖。比如在测试一个依赖其他服务(如账户服务、数据库访问服务等)的业务逻辑时,可模拟这些外部服务,避免在测试中涉及真实的复杂操作(如真的修改数据库数据、调用远程接口等) 。
  • 定义行为:可以对模拟对象的方法进行 “桩(Stubbing)” 设置,即指定其返回值或让其抛出异常。例如,使用when(...).thenReturn(...)来定义方法返回特定值;用thenThrow()模拟方法抛出异常,方便测试错误处理逻辑。
  • 验证交互:提供验证机制,通过verify(...)方法检查模拟对象的方法是否按照预期被调用,以及调用的次数,从而验证代码与模拟对象之间的交互是否正确

引入的依赖

mockito-core

<!-- https://mvnrepository.com/artifact/org.mockito/mockito-core -->
<dependency><groupId>org.mockito</groupId><artifactId>mockito-core</artifactId><version>5.15.2</version><scope>test</scope>
</dependency>

testng 

        <!-- https://mvnrepository.com/artifact/org.testng/testng --><dependency><groupId>org.testng</groupId><artifactId>testng</artifactId><version>7.11.0</version><scope>test</scope></dependency>

为什么需要mock

可以知道这个方法的调用情况,调用了多少次参数就是多少

给这个对象的行为做一个定义,来指定返回结果或者指定特定的动作

当使用mock对象时,如果不对其行为进行定义,则mock对象方法的返回值为返回类型的默认值


验证和断言

验证:vertify()方法

验证是校验待验证的对象是否发生过某些行为

package com.example.testng;import org.mockito.Mockito;
import org.testng.annotations.Test;import java.util.Random;public class MockitoDemoTest {@Testpublic void test(){//mock一个对象Random mock= Mockito.mock(Random.class);//输出随机数System.out.println(mock.nextInt());//验证我们的mock对象是否用了nextInt()这个方法Mockito.verify(mock).nextInt();}
}

为什么我们的执行结果一直是0?

这是因为我们没有给我们的mock出来的对象定义行为

断言:Assert

判断我们返回的结果是否符合我们的预期

package com.example.testng;import org.mockito.Mockito;
import org.testng.Assert;
import org.testng.annotations.Test;import java.util.Random;public class MockitoDemoTest {@Testpublic void test() {//mock一个对象Random mock = Mockito.mock(Random.class);Mockito.when(mock.nextInt()).thenReturn(100);Assert.assertEquals(100, mock.nextInt());}
}

符合预期,我们成功通过

不符合预期,我们测试失败

package com.example.testng;import org.mockito.Mockito;
import org.testng.Assert;
import org.testng.annotations.Test;import java.util.Random;public class MockitoDemoTest {@Testpublic void test() {//mock一个对象Random mock = Mockito.mock(Random.class);Mockito.when(mock.nextInt()).thenReturn(100);Assert.assertEquals(101, mock.nextInt());}
}


给Mock对象进行打桩

打桩的意思其实就是对mock对象的行为进行定义

打桩的话是mockito里面的when()方法,定义我们的行为


@Mock注解

我们的mock注解必须搭配MockitoAnnotations.openMocks(testClass)方法一起使用

我们使用@Mock注解来Mock对象,而不是在代码里面手动Mock我们的对象

package com.example.testng;import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.testng.Assert;
import org.testng.annotations.Test;import java.util.Random;public class MockitoDemoTest {@Mockprivate Random mock;@Testpublic void test() {MockitoAnnotations.openMocks(this);Mockito.when(mock.nextInt()).thenReturn(100);Assert.assertEquals(100, mock.nextInt());}
}

@BeforeTets与@AfterTest

package com.example.testng;import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.testng.Assert;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;import java.util.Random;public class MockitoDemoTest {@Mockprivate Random mock;@BeforeTestvoid setup() {System.out.println("测试前的准备");}@AfterTestvoid end() {System.out.println("测试结束");}@Testpublic void test() {MockitoAnnotations.openMocks(this);Mockito.when(mock.nextInt()).thenReturn(100);Assert.assertEquals(100, mock.nextInt());}
}


Spy方法与@Spy注解

spy方法与mock方法的不同是

1.被spy的对象会走真实的方法而mock对象不会

2.spy{}方法的参数是对象实例,mock的参数是class

package com.example.testng;import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import org.testng.Assert;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;import java.util.Random;public class MockitoDemoTest {@Spyprivate Random mock;@BeforeTestvoid setup() {MockitoAnnotations.openMocks(this);}@Testpublic void test() {Assert.assertEquals(100, mock.nextInt());}
}

我们没有打桩,而且我们是Spy注解,所以我们不会输出0,而是会去调用真正的Random方法

如果我们打桩了的话,那还是会按照我们打桩定义的规则来


打桩与Mock静态方法

4个常见的打桩方法

thenCallRealMethod

thenReturn

thenThrow

thenAnswer

package com.example.testng;import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.testng.Assert;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;import java.util.Random;import static org.mockito.Mockito.when;public class MockitoDemoTest {@Spyprivate Random mock;@BeforeTestvoid setup() {MockitoAnnotations.openMocks(this);}@Testpublic void test() {//调用真实方法when(mock.nextInt()).thenCallRealMethod();//定义返回值when(mock.nextInt()).thenReturn(1);//定义返回什么错误when(mock.nextInt()).thenThrow(new RuntimeException());//自定义响应逻辑when(mock.nextInt()).thenAnswer(new Answer<Integer>() {@Overridepublic Integer answer(InvocationOnMock invocation) throws Throwable {// 这里可以编写自定义的逻辑// invocation 包含了方法调用的信息,例如方法名、参数等// 这里简单返回一个固定值 42return 42;}});}
}

Mock静态方法

依赖

mockito-inline依赖包含了mockito-code依赖

注意我们使用mockito-inline依赖的时候要把mockito-code依赖注释掉,我们不能同时引用

<!-- https://mvnrepository.com/artifact/org.mockito/mockito-inline -->
<dependency><groupId>org.mockito</groupId><artifactId>mockito-inline</artifactId><version>5.2.0</version><scope>test</scope>
</dependency>

在软件开发的单元测试中,有时候我们需要对静态方法进行模拟(Mock),这样可以更好地控制测试环境、隔离依赖,提高测试的可维护性和稳定性。下面详细介绍模拟静态方法的相关内容,以 Java 语言结合 Mockito 框架为例


为什么需要 Mock 静态方法
 

隔离依赖:静态方法可能依赖于外部资源,如文件系统、数据库等。在单元测试中,我们希望避免这些外部依赖的影响,通过模拟静态方法可以将测试与外部资源隔离开来

控制返回值:静态方法的返回值可能受到多种因素的影响,通过模拟静态方法,我们可以精确控制其返回值,从而更方便地验证业务逻辑


使用例子

我们这个类里面有个静态方法

public class StaticUtils {public static int add(int a, int b) {return a + b;}
}

使用mockStatic

使用 try-with-resources语句确保 MockedStatic 对象在使用完毕后自动关闭,避免对后续测试产生影响

import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mockStatic;public class StaticUtilsTest {@Testpublic void testMockStaticMethod() {// 使用 try-with-resources 语句创建 MockedStatic 对象try (MockedStatic<StaticUtils> mockedStatic = mockStatic(StaticUtils.class)) {// 定义静态方法的行为mockedStatic.when(() -> StaticUtils.add(2, 3)).thenReturn(10);// 调用静态方法int result = StaticUtils.add(2, 3);// 验证结果assertEquals(10, result);}}
}

单元测试如何提高我们的代码覆盖率

@InjectMocks注解

剩下的@mock和@spy注解修饰的对象会自动注入到被InjectMocks注解修饰的对象里面

相关文章:

Java测试框架Mockito快速入门

Mockito结合TestNG快速入门 什么是Mockito Mockito 是一个专门用于 Java 的强大测试框架&#xff0c;主要用来创建和管理模拟对象&#xff0c;辅助开发者进行单元测试&#xff0c;具有以下特点和功能&#xff1a; 创建模拟对象&#xff1a;能通过简洁的语法创建类或接口的模…...

删除idea recent projects 记录

1、退出idea&#xff08;一定要全部退出idea&#xff0c;要不然删除后&#xff0c;idea一退出&#xff0c;又保存上了&#xff09; 2、进入 C:\Users\Administrator\AppData\Roaming\JetBrains\IntelliJIdea2024.1\options 目录 根据不同的版本号 IntelliJIdea2024.1 这个地方…...

16.2 LangChain 表达式语言设计哲学:重新定义大模型应用开发范式

LangChain 表达式语言设计哲学:重新定义大模型应用开发范式 关键词:LCEL 设计哲学、声明式编程范式、生产级应用架构、流式处理优化、模块化组合 1. 核心设计目标全景图 mindmap root((LCEL设计目标)) 开发效率 声明式编程 类型提示系统 自动补全支持 工程可靠性 错…...

LabVIEW 无法播放 AVI 视频的编解码器解决方案

用户在 LabVIEW 中使用示例程序 Read AVI File.vi&#xff08;路径&#xff1a; &#x1f4cc; C:\Program Files (x86)\National Instruments\LabVIEW 2019\examples\Vision\Files\Read AVI File.vi&#xff09;时发现&#xff1a; ✅ LabVIEW 自带的 AVI 视频可正常播放 这是…...

【Java进阶】java设计模式之单例模式

一、单例设计模式的基本概念 在 Java 编程的广阔天地里&#xff0c;单例设计模式宛如一颗璀璨的明星&#xff0c;是一种极为实用的创建型设计模式。它的核心使命是确保一个类在整个应用程序的生命周期内仅仅存在一个实例&#xff0c;并且为外界提供一个全局唯一的访问点来获取…...

AI编程界的集大成者——通义灵码AI程序员

一、引言 随着软件行业的快速发展和技术的进步&#xff0c;人工智能&#xff08;AI&#xff09;正在成为软件开发领域的一个重要组成部分。近年来&#xff0c;越来越多的AI辅助工具被引入到开发流程中&#xff0c;旨在提高效率、减少错误并加速创新。在这样的背景下&#xff0…...

第三十三:6.3. 【mitt】 任意组件通讯

概述&#xff1a;与消息订阅与发布&#xff08;pubsub&#xff09;功能类似&#xff0c;可以实现任意组件间通信。 // 引入mitt import mitt from "mitt";// 创建emitter const emitter mitt()/*// 绑定事件emitter.on(abc,(value)>{console.log(abc事件被触发,…...

6.7 数据库设计

文章目录 数据库设计6个阶段新奥尔良法完整导图 数据库设计6个阶段 数据库设计是指&#xff0c;根据应用环境&#xff0c;构造数据库模式&#xff0c;建立数据库、应用系统&#xff0c;实现有效地数据存储&#xff0c;以满足用户需求。 数据库设计过程包含6个阶段 数据库规划&…...

Java 大视界 -- Java 大数据在智能安防入侵检测与行为分析中的应用(108)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…...

Vue3实现文件上传、下载及预览全流程详解(含完整接口调用)

文章目录 一、环境准备1.1 创建Vue3项目1.2 安装依赖1.3 配置Element Plus 二、文件上传实现2.1 基础上传组件2.2 自定义上传逻辑&#xff08;Axios实现&#xff09; 三、文件下载实现3.1 直接下载&#xff08;已知文件URL&#xff09;3.2 后端接口下载&#xff08;二进制流&am…...

【云原生】SpringCloud-Spring Boot Starter使用测试

目录 Spring Boot Starter是什么&#xff1f; 以前传统的做法 使用 Spring Boot Starter 之后 starter 的理念&#xff1a; starter 的实现&#xff1a; ?创建Spring Boot Starter步骤 在idea新建一个starter项目、直接执行下一步即可生成项目。 ?在xml中加入如下配置…...

介绍下pdf打印工具类 JasperPrint

JasperPrint 工具类深度解析 JasperPrint 是 JasperReports 框架中实现 PDF 打印的核心载体类&#xff0c;其本质是 填充数据后的可打印报表对象&#xff0c;承担着从模板编译、数据填充到格式输出的全流程控制。以下从 7 个维度展开深度解析&#xff1a; 一、核心定位与生命周…...

idea中或pycharm中编写Markdown文件

参考 ltjt_aiseek: seek_backend_py 项目 数智科技ai探索API接口开发 1. 安装 Django 框架 在开始创建 Django 项目之前&#xff0c;需要先安装 Django 框架。可以通过 PyCharm 的终端或者系统的命令行工具来完成安装。 使用 PyCharm 终端安装 打开 PyCharm&#xff0c;如果…...

Go红队开发—并发编程

文章目录 并发编程go协程chan通道无缓冲通道有缓冲通道创建⽆缓冲和缓冲通道 等协程sync.WaitGroup同步Runtime包Gosched()Goexit() 区别 同步变量sync.Mutex互斥锁atomic原子变量 SelectTicker定时器控制并发数量核心机制 并发编程阶段练习重要的细节端口扫描股票监控 并发编程…...

使用自动化运维工具 Ansible 集中化管理服务器

一、概述 Ansible 是一款为类 Unix 系统开发的自由开源的配置和自动化工具 官方网站:https://www.ansible.com/ Ansible 成立于 2013 年,总部设在北卡罗来纳州达勒姆,联合创始人 ad Ziouani 和高级副总裁 Todd Barr都是红帽的老员工。Ansible 旗下的开源软件 Ansible 十分…...

数据集笔记:新加坡 一些交通的时间序列统计量

1 机动车年度保有量 data.gov.sg 各类机动车年度保有量 数据范围&#xff1a;2005年1月 - 2020年12月 1.1 数据说明 非高峰时段车辆 包括周末车&#xff08;Weekend Cars&#xff09;和 修订版非高峰时段车辆&#xff08;Revised Off Peak Cars&#xff09;&#xff0c;该…...

企业jsapi_ticket,java举例

在企业微信开发中&#xff0c;使用 Java 获取 jsapi_ticket 并生成签名的步骤如下。以下是完整的 Java 示例代码。 1. 获取 jsapi_ticket 的流程 获取 access_token。 使用 access_token 获取 jsapi_ticket。 使用 jsapi_ticket 生成签名&#xff08;signature&#xff09;。…...

【FL0090】基于SSM和微信小程序的球馆预约系统

&#x1f9d1;‍&#x1f4bb;博主介绍&#x1f9d1;‍&#x1f4bb; 全网粉丝10W,CSDN全栈领域优质创作者&#xff0c;博客之星、掘金/知乎/b站/华为云/阿里云等平台优质作者、专注于Java、小程序/APP、python、大数据等技术领域和毕业项目实战&#xff0c;以及程序定制化开发…...

智能图像处理平台:图像处理配置类

这里我们先修改一下依赖&#xff0c;不用JavaCV&#xff0c;用openCV。 导入依赖&#xff1a; <!-- JavaCV 依赖&#xff0c;用于图像和视频处理 --> <!-- <dependency>--> <!-- <groupId>org.bytedeco</groupId>--> &l…...

《深度剖析:生成对抗网络中生成器与判别器的高效协作之道》

在人工智能的前沿领域&#xff0c;生成对抗网络&#xff08;GAN&#xff09;以其独特的对抗学习机制&#xff0c;为数据生成和处理带来了革命性的变革。生成器与判别器作为GAN的核心组件&#xff0c;它们之间的协作效率直接决定了GAN在图像生成、数据增强、风格迁移等众多应用中…...

【多模态大模型论文精读】MinMo语音交互大模型

写在前面:你需要一个更丝滑的语音助手 想象一下,你与一个语音助手对话,不再需要“嘿,Siri”或“小爱同学”这样的唤醒词,也不需要等待它一字一句地蹦出回复。你们可以像朋友一样,随时打断、插话,甚至同时说话。语音助手不仅能听懂你说了什么,还能理解你的语气、情感,…...

22-接雨水

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 方法一&#xff1a;双指针法 思路 使用两个指针 left 和 right 分别指向数组的两端&#xff0c;同时记录左边的最大高度 leftMax 和右边的最大高度 rig…...

如何长期保存数据(不包括云存储)最安全有效?

互联网各领域资料分享专区(不定期更新): Sheet 前言 这个问题需要考虑多个方面,比如存储介质的寿命、数据完整性、访问的便捷性,还有成本等因素。长期保存的话,存储介质的耐久性很重要。比如常见的硬盘、SSD、光盘、磁带等,各有优缺点。机械硬盘(HDD)的寿命一般在3-5年,…...

k8s拉取harbor镜像部署

在k8s中创建凭证 首先在节点docker登录harbor&#xff0c; 登录成功之后会在$HOME/.docker/ 生成一个config.json文件&#xff0c;这个就是登录凭证&#xff0c;后面docker pull就不需要再登录了。但是如果在k8s发布pod或者deploment时&#xff0c;这个凭证要在k8s中创建一个对…...

一周一个Unity小游戏2D反弹球游戏 - 球板的发球

前言 本文将实现当游戏开始时球在球板上,且不具备物理性,在Windows平台上通过点击屏幕来球发射,安卓平台上当手指触摸到屏幕上时进行发球,并此时开始具备物理性。 发球逻辑 首先在球板上创建一个球的发射点,新建一个空的游戏物体,并命名为BallPoint,并将其作为SpringBoa…...

C 语言共用体:深入理解与实践】

目录 一、引言 二、共用体的定义和基本语法 三、共用体的使用 3.1 声明共用体变量 3.2 给共用体成员赋值 3.3 共用体的内存布局 四、共用体的应用场景 4.1 节省内存空间 4.2 处理不同类型的数据 五、共用体使用的注意事项 六、总结 一、引言 在 C 语言中&#xff0c;共…...

Oracle性能调优(一):时间模型统计

Oracle性能调优(一):时间模型统计 时间模型统计视图时间模型统计指标时间模型统计视图 📖 DB Time的含义: DB Time表示前台会话在数据库调用中所花费的总时间,它是衡量数据库实例总负载的一个重要指标。DB Time是从实例启动时开始累计测量的,其计算方法是将所有前台会话…...

012 rocketmq事务消息

文章目录 事务消息概念介绍交互流程事务消息原理TransactionListener接⼝TransactionProducer.javaTransactionConsumer.java 事务消息 内置topic中的消息对消费者不可见 本地事务mq消息事务消息 消息队列 RocketMQ 版提供的分布式事务消息适⽤于所有对数据最终⼀致性有强需求…...

SpringBoot原理-02.自动配置-概述

一.自动配置 所谓自动配置&#xff0c;就是Spring容器启动后&#xff0c;一些配置类、bean对象就自动存入了IOC容器当中&#xff0c;而不需要我们手动声明&#xff0c;直接从IOC容器中引入即可。省去了繁琐的配置操作。 我们可以首先将spring项目启动起来&#xff0c;里面有一…...

知识图谱+智能问诊预诊系统vue+django+neo4j架构、带问诊历史

文章结尾部分有CSDN官方提供的学长 联系方式名片 文章结尾部分有CSDN官方提供的学长 联系方式名片 关注B站&#xff0c;有好处&#xff01; &#x1f90d;编号&#xff1a;D032 &#x1f90d;智能问答&#xff1a;智能问答自诊、预诊功能&#xff0c;同时可以保存问答历史 &…...