基于mockito做单元测试

1.简介

  • 配合断言使用(杜绝System.out)
  • 可重复执行
  • 不依赖环境
  • 不会对数据产生影响
  • Spring的上下文环境不是必备的
  • 一般都配合mock类框架对数据库进行隔离

mock类使用场景:

要进行测试的方法存在外部依赖(DB,Redis,第三方接口),为了专注于对该方法的逻辑进行测试,就希望能隔离出来外部依赖,避免外部依赖成为单测的阻塞项,一般单测都是在service进行测试

创建mock对象的三种方法:

/*** 创建mock对象的第一种方法*/
@ExtendWith(MockitoExtension.class)
public class InitMockOrSpyMethod1 {@Mockprivate UserService mockUserService;@Spyprivate UserService spyUserServices;@Testpublic void test1(){System.out.println("Mockito.mockingDetails(mockUserService).isMock():"+Mockito.mockingDetails(mockUserService).isMock());System.out.println("Mockito.mockingDetails(mockUserService).isSpy():"+Mockito.mockingDetails(mockUserService).isSpy());System.out.println("Mockito.mockingDetails(spyUserServiceS).isMock():"+Mockito.mockingDetails(spyUserServices).isMock());// spy对象是另一种类型的mock对象System.out.println("Mockito.mockingDetails(spyUserServiceS).isSpy():"+Mockito.mockingDetails(spyUserServices).isSpy());}}
/*** 创建mock对象的第二种方法*/
public class InitMockOrSpyMethod2 {private UserService mockUserService;private UserService spyUserServices;@BeforeEachpublic void init(){mockUserService = Mockito.mock(UserService.class);spyUserServices = Mockito.spy(UserService.class);}@Testpublic void test1(){System.out.println("Mockito.mockingDetails(mockUserService).isMock():"+Mockito.mockingDetails(mockUserService).isMock());System.out.println("Mockito.mockingDetails(mockUserService).isSpy():"+Mockito.mockingDetails(mockUserService).isSpy());System.out.println("Mockito.mockingDetails(spyUserServiceS).isMock():"+Mockito.mockingDetails(spyUserServices).isMock());// spy对象是另一种类型的mock对象System.out.println("Mockito.mockingDetails(spyUserServiceS).isSpy():"+Mockito.mockingDetails(spyUserServices).isSpy());}
}
/*** 创建mock对象的第三种方法*/
public class InitMockOrSpyMethod3 {@Mockprivate UserService mockUserService;@Spyprivate UserService spyUserServices;@BeforeEachpublic void init(){MockitoAnnotations.openMocks(this);}@Testpublic void test1(){System.out.println("Mockito.mockingDetails(mockUserService).isMock():"+Mockito.mockingDetails(mockUserService).isMock());System.out.println("Mockito.mockingDetails(mockUserService).isSpy():"+Mockito.mockingDetails(mockUserService).isSpy());System.out.println("Mockito.mockingDetails(spyUserServiceS).isMock():"+Mockito.mockingDetails(spyUserServices).isMock());// spy对象是另一种类型的mock对象System.out.println("Mockito.mockingDetails(spyUserServiceS).isSpy():"+Mockito.mockingDetails(spyUserServices).isSpy());}
}

2.mock和spy对象

mock对象:

  • 方法插桩:执行插桩逻辑
  • 方法不插桩:返回mock对象的默认值
  • 作用对象:类吗,接口

spy对象:

  • 方法插桩:执行插桩逻辑
  • 方法不插桩:调用真实方法
  • 作用对象:类吗,接口

3.参数匹配

@Test
public void test1() {UserDO userDO = new UserDO();userDO.setId(1L);doReturn("nothing").when(mockUserService).selectNameById(userDO.getId());// 只有执行Mockito.doReturn才执行插桩System.out.println(mockUserService.selectNameById(userDO.getId()));// userDO2对象不进行插桩,返回默认值UserDO userDO2 = new UserDO();userDO2.setId(2L);System.out.println(mockUserService.selectNameById(userDO2.getId()));
}
    /*** 此时我只想拦截UserDO类型的任意对象* ArgumentMatchers.*拦截任意类型*/@Testpublic void test2() {doReturn("nothingName").when(mockUserService).selectNameById(ArgumentMatchers.anyLong());UserDO userDO = new UserDO();userDO.setId(1L);System.out.println(mockUserService.selectNameById(userDO.getId()));UserDO userDO2 = new UserDO();userDO2.setId(2L);System.out.println(mockUserService.selectNameById(userDO2.getId()));}

方法插桩

指定调用某个方法时的行为,达到相互隔离的效果

  • 返回指定值
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.when;@ExtendWith(MockitoExtension.class)
public class StubTest {@Mockprivate List<String> mockList;/*** 指定返回值*/@Testpublic void test1() {// 方法一doReturn("zero").when(mockList).get(0);// 如果返回值不相等,则测试不通过Assertions.assertEquals("zero", mockList.get(0));//方法二when(mockList.get(1)).thenReturn("one");Assertions.assertEquals("one", mockList.get(1));}
}
  • void返回值方法插桩
/*** void 返回值插桩*/
@Test
public void test2() {// 调用mockList.clear()什么也没做doNothing().when(mockList).clear();mockList.clear();verify(mockList, times(1)).clear();
}
  • 插桩的两种形式

    • when(obj.someMethod.thenXXX):用于mock对象
    • doXXX():用于mock/spy对象

    区别在于不插桩时doXXX应用与spy对象时会调用真实方法

    public void test4() {when(mockUserServiceImpl.getNumber()).thenReturn(99);System.out.println("mockUserServiceImpl.getNumber():"+mockUserServiceImpl.getNumber());doReturn(99).when(spyUserServiceImpl).getNumber();System.out.println("spyUserServiceImpl.getNumber() = " + spyUserServiceImpl.getNumber());
    }
    
  • 抛异常

/*** 断言异常*/@Testpublic void test3() {doThrow(RuntimeException.class).when(mockList).get(anyInt());try{mockList.get(10000);//此处get(10000)为空Assertions.fail();}catch (RuntimeException e){// 断言表达式为真Assertions.assertTrue(e instanceof RuntimeException);}}
  • 多次插桩
/*** 多次插桩*/@Testpublic void test4() {// 第一次调用返回1,第二次返回2,第三次返回3以及以后得调用都返回三when(mockList.size()).thenReturn(1).thenReturn(2).thenReturn(3);Assertions.assertEquals(1,mockList.size());Assertions.assertEquals(2,mockList.size());Assertions.assertEquals(3,mockList.size());Assertions.assertEquals(4,mockList.size());}
  • thenAnswer
/*** thenAnswer:实现指定的插桩逻辑*/@Testpublic void test5() {// 此处不管传入什么参数,都返回100*3when(mockList.get(anyInt())).thenAnswer(new Answer<String>() {/*** 泛型是要返回插桩的返回值类型* @param invocationOnMock* @return* @throws Throwable*/@Overridepublic String answer(InvocationOnMock invocationOnMock) throws Throwable {Integer argument = invocationOnMock.getArgument(0, Integer.class);return String.valueOf(argument*100);}});String s = mockList.get(3);Assertions.assertEquals("300",s);}
  • 执行真正的原始方法
/*** 执行真正的原始方法*/@Testpublic void test6() {when(mockUserServiceImpl.getNumber()).thenCallRealMethod();int number = mockUserServiceImpl.getNumber();Assertions.assertEquals(1,number);}
  • verify的使用
    /*** 指定方法返回几次*/@Testpublic void test3() {mockUserService.add("lily", "123123", new ArrayList<>());// 验证add方法被调用了1次Mockito.verify(mockUserService, Mockito.times(1)).add("lily", "123123", new ArrayList<>());// 要么全部使用ArgumentMatchers,不能一半使用参数,一半使用ArgumentMatchersMockito.verify(mockUserService, Mockito.times(1)).add(ArgumentMatchers.anyString(), ArgumentMatchers.anyString(), ArgumentMatchers.anyList());}

4.@InjectMocks注解

  • 作用:如果@InjectMocks声明的变量需要用到mock,spy对象,mockito会自动使用当前类里的mock或者spy成员进行an类型或者名字注入
  • 原理:构造器注入,setter注入,字段反射注入
@ExtendWith(MockitoExtension.class)
public class InjectMocksTest {/*** 被InjectMocks标注的属性,必须是实现类,因为Mockito会创建InjectMocks注解的类的实例,* 并注入到被InjectMocks标注的属性中,默认创建的对象就是没有经过Mockito处理过的对象,因此* 配合@Spy注解,变成可以调用默认方法的mock对象*/@InjectMocks@Spyprivate UserServiceImpl userService;@Mockprivate UserFeatureService userFeatureService;@Testpublic void test() {int number = userService.getNumber();Assertions.assertEquals(1, number);}
}

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

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

相关文章

计算机毕业设计 社区医疗服务系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

国产游戏技术能否引领全球【终稿】

国产游戏技术能否引领全球 摘要&#xff1a;近年来&#xff0c;国产游戏行业蓬勃发展&#xff0c;技术水平不断提升&#xff0c;多款作品在国际市场上崭露头角。从画面渲染到物理引擎&#xff0c;从AI技术到服务器架构&#xff0c;中国游戏开发者在各个领域都取得了显著进步。…

MySQL高阶1919-兴趣相同的朋友

题目 请写一段SQL查询获取到兴趣相同的朋友。用户 x 和 用户 y 是兴趣相同的朋友&#xff0c;需满足下述条件&#xff1a; 用户 x 和 y 是朋友&#xff0c;并且用户 x and y 在同一天内听过相同的歌曲&#xff0c;且数量大于等于三首. 结果表 无需排序 。注意&#xff1a;返…

常见排序(C语言版)

1.排序的概念及其应用 1.1排序的概念 排序&#xff1a;​ 在计算机科学与数学中&#xff0c;一个排序算法&#xff08;英语&#xff1a;Sorting algorithm&#xff09;是一种能将一串资料依照特定排序方式排列的算法。 稳定性&#xff1a;假定在待排序的记录序列中&#xff…

聚观早报 | 小米三折叠手机专利曝光;李斌谈合肥投资蔚来

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 9月20日消息 小米三折叠手机专利曝光 李斌谈合肥投资蔚来 索尼PS5 Pro包装亮相 新一代Spectacles AR眼镜发布 通…

三十种编程语言庆祝【国庆节】!!!

30种编程语言来打印“国庆节快乐”&#xff1a; 分别为&#xff1a; PythonJavaScriptJavaCCC#PHPRubySwiftGoRustKotlinScalaPerlRLuaDartTypeScriptBash (Shell)F#JuliaElixirHaskellGroovyVisual Basic .NETMATLABPowerShellSQLVBA (Visual Basic for Applications)COBOL …

《AI系统:原理与架构》于华为HC大会2024正式发布

2024年9月21日&#xff0c;《AI系统&#xff1a;原理与架构》新书发布会在上海世博馆华为HC大会顺利举办。本书由华为昇腾技术专家、B站AI科普博主ZOMI酱和哈工大软件学院副院长苏统华教授联合编写&#xff0c;是领域内AI系统方面填补空白的重磅之作。 发布会上&#xff0c;《A…

Spring:项目中的统一异常处理和自定义异常

介绍异常的处理方式。在项目中&#xff0c;都会进行自定义异常&#xff0c;并且都是需要配合统一结果返回进行使用。 1.背景引入 &#xff08;1&#xff09;背景介绍 为什么要处理异常&#xff1f;如果不处理项目中的异常信息&#xff0c;前端访问我们后端就是显示访问失败的…

【监控】【Nginx】使用 Zabbix 监控 Nginx,并使用 InfluxDB 存储数据的详细指南

目录 1. 安装 Zabbix Server步骤 1&#xff1a;安装 Zabbix 服务器步骤 2&#xff1a;安装 InfluxDB步骤 3&#xff1a;启动 InfluxDB 服务步骤 4&#xff1a;创建 InfluxDB 数据库步骤 5&#xff1a;配置 Zabbix Server步骤 6&#xff1a;启动 Zabbix 服务 2. 安装 Zabbix Age…

JavaScript发送邮件:实现前端触发的教程?

JavaScript发送邮件的方式&#xff1f;怎么使用JavaScript发信&#xff1f; 无论是用户反馈、联系表单还是自动通知&#xff0c;前端触发的邮件发送功能都能极大地提升用户体验。AokSend将详细介绍如何通过JavaScript发送邮件&#xff0c;实现前端触发的邮件发送功能。 JavaS…

Centos7安装chrome的问题

chrome是129版本的&#xff0c;很新。 启动chrome的时候报错&#xff1a;undefined symbol: ippvalidateattributes 这个没有报libxxx.so not found。 大概就是依赖的so库版本太低了&#xff0c;查了下这个函数在cups 重新拉了最新的代码并编译 ./configure --with-tlsno…

跨站请求伪造(CSRF)漏洞详解

免责申明 本文仅是用于学习检测自己搭建的DVWA靶场环境有关CSRF的原理和攻击实验,请勿用在非法途径上,若将其用于非法目的,所造成的一切后果由您自行承担,产生的一切风险和后果与笔者无关;本文开始前请认真详细学习《‌中华人民共和国网络安全法》‌及其所在国家地区相关法…

ubuntu24安装vivado24(安装并解决若干错误)

目录 安装方法&#xff1a;问题1&#xff1a;解决办法&#xff1a; 问题2&#xff1a;解决方法&#xff1a; 安装完成&#xff1a; 安装方法&#xff1a; 注意&#xff1a;内存最好预留80G空闲的。 安装好大小&#xff1a; 安装依赖库&#xff1a; sudo apt-get update sud…

计算机网络17——IM聊天系统——客户端核心处理类框架搭建

目的 拆开客户端和服务端&#xff0c;使用Qt实现客户端&#xff0c;VS实现服务端 Qt创建项目 Qt文件类型 .pro文件&#xff1a;配置文件&#xff0c;决定了哪些文件参与编译&#xff0c;怎样参与编译 .h .cpp .ui&#xff1a;画图文件 Qt编码方式 Qt使用utf-8作为编码方…

Java 8 和 MyBatis 框架实现每天凌晨 2 点进行增量缓存

以下是使用 Java 8 和 MyBatis 框架实现每天凌晨 2 点进行增量缓存的完整示例代码&#xff1a; Offering 实体类&#xff1a; public class Offering { private String id; private String name; private String size; private String type; // 构造方法、get…

堆栈指针寄存器SP的初值是多少?执行PUSH AX命令后,SP的值是多少?执行POP BX后,SP的值是多少?为什么答案给的是200,202,200。

欢迎来到我的技术博客&#xff01; &#x1f389; 这里不仅有满满的编程干货和学习资源&#xff0c;我的某站账号也为你准备了更多实用的技术视频和知识分享。 &#x1f449; 点击关注我的小破站账号&#xff0c;获取更多编程技巧和学习资源&#xff01; 小破站主页 例题 ST…

鸿蒙 WebView 如何 Debug

前置&#xff1a; hdc chrome //----------------------------------------------------------------------------------------------- hdc shell cat /proc/net/unix | grep devtools 0: 00000002 0 10000 1 1 81134005 webview_devtools_remote_62479exit执行&…

vulnhub(12):bob 1.0.1(gpg文件解密)

端口 nmap主机发现 nmap -sn 192.168.72.0/24 ​ Nmap scan report for 192.168.72.169 Host is up (0.00020s latency). ​ 169是新出现的机器&#xff0c;他就是靶机 nmap端口扫描 nmap -Pn -sV 192.168.72.169 -p- --min-rate 10000 -oA nmap/scan 扫描开放端口保存到 nmap…

STL简介

在了解了C中的类和对象以及内存管理基本的知识后接下来我们将进入STL的学习&#xff0c;在此我们在本篇会先了解STL的由来以及大致了解STL的组成&#xff0c;接下来在之后的篇章中我将依次来学string、vector等&#xff0c;学习完STL之后相信你会进一步了解C的魅力所在。接下来…

后台数据管理系统 - 项目架构设计-Vue3+axios+Element-plus(0917)

七、引入 element-ui 组件库 我的Git仓库&#xff1a;https://gitee.com/msyycn/vue3-hei-ma.git 官方文档&#xff1a; https://element-plus.org/zh-CN/ 安装 $ pnpm add element-plus自动按需&#xff1a; 安装插件 pnpm add -D unplugin-vue-components unplugin-auto…