首页 > 其他分享 >基于 Mockito 框架的 Mock 测试

基于 Mockito 框架的 Mock 测试

时间:2024-07-20 22:26:51浏览次数:15  
标签:调用 框架 对象 Mockito 测试 方法 插桩 Mock

1.什么是 Mock 测试

Mock 通常是指,在测试一个对象 A 时,我们构造一些假的对象(一般是不容易构造或者不容易获取的对象,比如测试类所依赖的实现类、第三方接口、数据库操作对象)来模拟与 A 之间的交互,这些对象被称为 Mock 对象,而 Mock 对象的行为是我们事先设定且符合预期。通过这些 Mock 对象来测试 A 在正常逻辑,异常逻辑或压力情况下工作是否正常。

下面是一个例子:

image.png|400

当我们需要测试 OrderService 时,按照我们常规的做法呢,都是要先准备好 redis,跟 db 的环境,然后构造UserService 跟 CouponService 注入进来,此时需要构建完整的依赖树,其过程是比较繁琐的,万一数据库连不上,依赖找不到,服务挂了… 时间一长可能会打击我们对项目进行单测的积极性,所以这时候很有必要寻求一种优雅的方式来解决。即,把这些依赖都转成 Mock 对象,作为模拟,将测试的重点专注于开发的功能逻辑。

2.常用注解

2.1@Mock

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

可以通过插桩的方式来模拟对象的行为。

2.2@Spy

用于创建一个部分模拟对象,它也属于 mock 对象的一种。但与@Mock不同,@Spy创建的是一个实际对象的代理,并且允许你选择性地模拟对象中的某些方法。默认情况下,所有未被特别模拟的方法都会调用实际对象的方法,通常与 doReturn/doThrow 等方法结合使用。一般是加在要测试的方法所在的类对象上,即加了 @InjectMocks 注解的位置。

2.3@InjectMocks

一般标注在被测对象上(必须是实现类),因为 mockito 会为添加了 @InjectMocks 注解的属性创建对应的实例对象。默认创建的对象就是一个普通的对象。经常需要配合 @Spy 注解使其变为默认调用真实方法的 mock 对象(可以理解为一个支持插桩的真实对象)。此外,mockito 会将 @Mock 和 @Spy 标注的对象注入到添加了 @InjectMocks 注解的被测对象中。

@InjectMocks
@Spy
private UserServiceImpl UserServiceImplTest;

@Mock
private UserFeatureService userFeatureService;

@Mock
private List<String> mockList;

一点总结:

方法插桩方法不插桩作用对象
Mock 对象执行插桩逻辑返回 mock 对象的默认值(不会去调用真实实现类方法)被测试类的依赖项
Spy 对象执行插桩逻辑调用真实方法被测试的实现类

3.常见操作

3.1插桩

  • when(xxxService.someMethod()).thenXxx(…):其中 xxxService 可以是 mock 对象。
  • doXXX().when(xxxService).someMethod():其中 xxxService 可以是 mock/spy 对象。

推荐是使用 doXXX()… 的插桩方式,因为对于 spy 对象,如果采用 when(…)… 的方式,会先执行真实的方法,比如会先执行一段打印的逻辑,而这不是我们想要的(即使由于插桩,最终返回的是插桩时指定的返回)。

常见的几种用法:

  • 指定返回
  • 指定抛出异常
  • 多次插桩
  • thenAnswer 指定实现自定义逻辑的插桩
@Test
public void test()(
    when(mockList.get(anyInt())).thenAnswer(newAnswer<String>(){
        /**
        *泛型表示要插桩方法的返回值类型
        */
        @override
        public String answer(InvocationOnMock invocation) throws Throwable{
            // getArgument表示获取插桩方法(此处就是List.get)的第几个参数值
            Integer argument = invocation.getArgument(index: 0, Integer.class);
            return String.valueof(argument* 100);
        }
});
    String result = mockList.get(3);
    Assertions.assertEquals(expected:"3ee",result);
}

3.2执行真实的方法

Mock 对象也可以执行真实的方法,只要在插桩时指定让他去调用真实方法即可。

Spy 对象,不插桩时即是执行真实方法。

3.3verify

可以用于验证某个方法是否被调用、被调用了几次、至少/至多调用了几次。且可以指定匹配的参数。此外,即使该方法被调用多次,但参数未匹配上,那也是不算的。

Verify 的另一个作用是对没有返回值的方法进行验证,证明其至少是被调用过的。

@Mock
private UserService userService;

@Test
public void test1() {
    userService.addUser("张三", "25", "男")
    // 通过
    verify(userService, times(1)).addUser("张三","25","男");
    // 不通过
    verify(userService, times(1)).addUser("李四","25","男");
    // 通过
    verify(userService, times(1)).addUser(anyString(),anyString(),anyString());
}

3.4断言

断言可用于对有返回值的方法进行判断。

也可以对没有返回值的方法进行判断:

Assertions.assertDoesNotThrow(() -> userServiceImplUnderTest.add("张三","25"));

4.基本思路

  1. 对于非测试方法进行 mock(一般是插桩),一般是数据库,或其他类方法的调用;
  2. 调用需要测试的方法;
  3. 实时修改(插桩、添加断言等);

5.参考

  1. 视频,有案例,讲的挺清楚的。mockito加junit搞定单元测试
  2. Java单元测试神器之Mockito - 掘金
  3. 这篇很全:Mockito测试框架入门与使用
  4. 对mock基本概念的介绍挺好的:单元测试 - Mockito 详解
  5. 单元测试 - Mockito 详解

标签:调用,框架,对象,Mockito,测试,方法,插桩,Mock
From: https://blog.csdn.net/weixin_43987408/article/details/140578340

相关文章

  • YOLOv8改进 | Neck | 注意力尺度序列融合的检测框架ASF-YOLO
    秋招面试专栏推荐:深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转......
  • Known框架实战演练——进销存数据结构
    系统主要包含商品信息、商业伙伴(客户、供应商)信息、业务单表头信息、业务单表体信息、对账单表头信息、对账单表体信息。1.商品信息(JxGoods)该表用于存储公司商品信息。名称代码类型长度必填商品信息JxGoods商品编码CodeText50Y商品名称NameText2......
  • 手把手教你搭建Mybatis框架
    目录Mybatis概述Mybatis环境搭建①在数据库里创建一张表②在maven项目中创建一个实体类③导入所需jar包 ④创建Mybatis核心配置文件⑤定义接口⑥ 创建sql映射文件⑦测试MybatisMybatisX插件Mybatis概述 • Mybatis原是apache的一个开源项目,起初叫iba......
  • Known框架实战演练——进销存系统需求
    概述该项目是一个开源、简易、轻量级的进销存管理系统,作为Known框架的实战演练项目。项目代码:JxcLite开源地址:https://gitee.com/known/JxcLite功能模块1.基础数据1.1数据字典框架内置模块,该模块用于维护系统下拉选项的数据,如商品类别、计量单位、结算方式等。栏位如......
  • Langchain 与 LlamaIndex:LLM 应用开发框架的比较与使用建议
    Langchain和Llamaindex是两种广泛使用的主流LLM应用开发框架。两者有什么不同?我们该如何使用?以下我根据各类资料和相关文档做了初步选型。一、Langchain1.适用场景(1)需要构建灵活、可扩展的通用应用程序。(2)需要复杂的工作流程支持。(3)需要复杂的交互和上下文保留功能。(4......
  • JAVA面试框架篇(SSM和MyBatis)
    框架篇一.Spring1.Spring1.1Bean生命周期1.2Bean循环依赖(引用)说说spring中的循环引用构造方法出现了循环依赖怎么解决?1.3Bean线程安全问题问题:Spring中的Bean是线程安全的吗?1.4AOP(什么是AOP?)AOP:AspectOrientedProgramming面向切面编程应用场景(你们项目中有没有......
  • 为了让Go开发变得更简单我把传统多层结构改为准单层(也可以认为两个实则一层,以为有一层
    前言自从使用上Go语言我们把开发简单贯彻到底,一个语言是否用得到舒服吗,我们一方面是看语言本身,另一方面还得有个好用框架,我们开发项目一般是不会从零开始编写代码,都是找个框架,在框架基础上搭建自己业务。所以我们一直想有一个满足开发简单、维护简单、学习简单、性能优秀、安......
  • Facebook 开源 C++ 框架 Ocean:用于计算机视觉和增强现实
    Facebook开源C++框架Ocean:用于计算机视觉和增强现实来源:OSCHINA编辑: 局2024-07-1211:05:00 0Facebook开源了其内部用于计算机视觉(CV)和增强现实(AR) 应用程序的框架Ocean,用于执行各种任务,包括计算机视觉、几何、媒体处理、网络和渲染。Ocean......
  • 腾讯开源可控视频生成框架 MimicMotion
    腾讯开源可控视频生成框架MimicMotion来源:投稿作者: 菠萝的海子2024-07-1617:01:19 4腾讯宣布开源可控视频生成框架MimicMotion,该框架可以通过提供参考人像及由骨骼序列表示的动作,来产生平滑的高质量人体动作视频。公告称,大量的实验结果和用户调研表明Mim......
  • [附开题]flask框架的基于web的线上考试管理系统的设计与实现n1qn5(python+源码)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景随着互联网技术的飞速发展,教育领域正经历着深刻的变革。传统的线下考试模式逐渐显露出其局限性,如组织成本高、效率低下、资源分配不均等问......