UT单元测试

news2024/10/7 14:30:17

Tips:在使用时一定要注意版本适配性问题

一、Mockito

1.1 Mock的使用

Mock 的中文译为仿制的,模拟的,虚假的。对于测试框架来说,即构造出一个模拟/虚假的对象,使我们的测试能顺利进行下去。

Mock 测试就是在测试过程中,对于某些 不容易构造(如 HttpServletRequest 必须在 Servlet 容器中才能构造出来)或者不容易获取 比较复杂 的对象(如 JDBC 中的 ResultSet对象),用一个 虚拟 的对象(Mock 对象)来创建,以便测试方法。

@Mock 注解用于创建模拟对象,而 @InjectMocks 注解用于注入依赖的模拟对象或真实对象到测试对象中。通常情况下,@Mock 和 @InjectMocks 会配合使用,在单元测试中提供模拟对象和被测试对象之间的依赖关系。

public class BookService {

    private BookRepository bookRepository;

    public BookService(BookRepository bookRepository) {
        this.bookRepository = bookRepository;
    }

    public Book findBook(String id) {
        return bookRepository.findById(id);
    }
}

@ExtendWith(MockitoExtension.class)
class BookServiceTest {

    @Mock
    private BookRepository bookRepository;

    @InjectMocks
    private BookService bookService;

    @Test
    void findBook() {
        Book book = new Book("1", "Title");
        when(bookRepository.findById("1")).thenReturn(book);

        bookService.findBook("1");

        verify(bookRepository, times(1)).findById("1");
    }
}

创建了一个模拟的 BookRepository,并且使用了 @InjectMocks 将它注入到了 BookService 的实例中。

1.2  @Mock @Spy @InjectMocks

  • @Mock:创建一个模拟对象(mocked object)。对其进行设置后,@Mock 创建的对象会返回设置好的值而不是执行真实的逻辑。
  • @Spy:创建一个间谍对象(spied object)。它和真实的对象很类似,除非明确设定,否则都是调用真实的方法。
  • @InjectMocks:创建一个实例,其余用 @Mock(或 @Spy)注解创建的mock会被注入到用 @InjectMocks 注解的类中。

Q1:既然@spy调用的是真实方法,那我为什么要使用这个注解呢,我直接在需要模拟的方法时候使用mock不就可以了吗

A:@Spy 是在你只想模拟类的部分行为,而其他方法还希望执行真实的逻辑时非常有用的。

@Spy
List<String> spyList = new ArrayList<String>();

@Test
public void testSpy() {
    spyList.add("one");
    spyList.add("two");

    // 在spy对象上设定返回预期值
    Mockito.doReturn(100).when(spyList).size();

    assertEquals(100, spyList.size());
    assertEquals("one", spyList.get(0));
}

1.3  @mockbean与@SpyBean

@MockBean 和 @SpyBean 是 Spring Boot 测试中常用的两个注解。下面是它们各自的特性:

  1. @MockBean

    • @MockBean 用于在 Spring 上下文中创建一个 Mock 对象,用它替换任何同类型的原有 Bean。
    • @MockBean 创建的mock对象没有任何实际行为,只返回预设的值。
    • 使用 @MockBean,你可以设置对其进行调用的各个方法的预期返回值。
  2. @SpyBean

    • @SpyBean 用于在 Spring 上下文中创建一个 Spy 对象,用它替换任何同类型的原有的 Bean。
    • @SpyBean 创建的 spy 对象基于实际的 Bean,事实上它就是原有 Bean 的一个复制体。除非明确地设定,否则它的方法调用结果与原有 Bean 完全相同。
    • 使用 @SpyBean,你可以监视(或跟踪)Bean 的行为,并能在需要时们改变某些方法的行为。

总的来说,@MockBean 和 @SpyBean 的核心区别是:@MockBean 创建的是一个可配置的纯 mock 对象,而 @SpyBean 则是基于一个实际对象的副本,这个副本中的方法调用能够反映出原有对象的行为。

使用场景:

@MockBean使用场景和代码示例

使用场景:我们通常在Spring的集成测试中使用@MockBean,这个注解用于替换Spring应用程序上下文中的现有Bean。它创建了一个Mock实例,并使用它替换原本的Bean。

@SpyBean使用场景和代码示例

使用场景:当我们希望监测真实的Bean时,我们使用@SpyBean。一个 Spy Bean 是一个代理,在这个代理中,被Spy的Bean的所有方法都会像平常一样被调用,除非我们明确地改变它们的行为。

 1.4 verify的使用方法及场景

Mockito.verify() 方法是 Mockito 框架中用于验证 mock 对象方法调用的工具。通过 verify() 方法,我们可以检查 mock 对象的某个方法是否被调用了,并可以进一步验证调用次数、调用顺序、传入参数等情况。

下面是 Mockito.verify() 方法的基本使用方法及一些常见应用场景:

验证方法是否被调用:

// 创建 mock 对象
List<String> mockList = Mockito.mock(List.class);

// 调用被测试的方法
mockList.add("test");

// 验证方法 add 是否被调用过一次
Mockito.verify(mockList).add("test");

这两个方法里面的参数必须一样才能进行验证。如果你要验证的方法参数与实际调用的方法参数不一样,那么 Mockito.verify() 方法会抛出异常并提示参数不匹配。

 验证方法被调用次数:

// 验证方法 add 被调用了两次
Mockito.verify(mockList, Mockito.times(2)).add("test");

 验证方法未被调用:

// 验证方法 add 未被调用
Mockito.verify(mockList, Mockito.never()).add("test");

 验证方法在特定顺序下被调用:

// 模拟方法调用
InOrder inOrder = Mockito.inOrder(mockList);
inOrder.verify(mockList).add("first");
inOrder.verify(mockList).add("second");

 验证方法传入参数:

// 验证方法 add 是否被调用,并且传入参数为字符串 "hello"
Mockito.verify(mockList).add(Mockito.eq("hello"));

 验证方法在特定时间内被调用:

// 验证方法 add 在100ms内是否被调用
Mockito.verify(mockList, Mockito.timeout(100)).add("test");

二、Junit5注解及断言

2.1 Junit5内置注解

2.2 junit5内置断言

三、Mockito 和 PowerMock的差异对比

Mockito 和 PowerMock 是两种广泛使用的 Java 单元测试模拟框架。它们都提供了创建和管理 mock 对象的能力,以帮助我们隔离并测试代码。然而,它们各自的特性使得它们在特定的场景中更有效。

Mockito 特性:

  1. 是目前最流行的 mocking 框架。
  2. 它能实现对方法的调用进行模拟,并验证方法的调用情况,通过一种优雅且简洁的 API 来提供这种功能。
  3. Mockito 不支持 mock 私有,静态和 fianl 方法或类的模拟
  4. Mockito 的语法简单且易于阅读,代码可维护性更高。
  5. Mockito 更关注于“测试行为”,而非“测试结果”。

PowerMock 特性:

  1. PowerMock 是 Mockito 和 EasyMock 的扩展,它能够模拟更加复杂的场景,包括静态方法,构造器,final 类及方法,私有方法等。
  2. PowerMock 使用字节码操作技术,通过在运行时修改字节码的方式实现这些复杂的模拟。
  3. PowerMock 能够执行更深层次的测试,但复杂的特性可能导致代码难以阅读和维护。
  4. PowerMock 适合用来模拟那些传统上被视为不可模拟的代码。

两者的主要使用场景:

  • Mockito 适合用于大多数标准的模拟情况,可以覆盖大部分的日常测试需求。其简单、易读的 API 使其成为首选工具。
  • PowerMock 的使用场景则更为具体,如必须模拟静态方法、final 类/方法或私有方法等情况。不过使用 PowerMock 应慎重,这些能力常常提示代码设计存在问题。

 使用powerMock模拟mock静态方法

public class UtilityClass {
    static int staticMethod(long value) {
        return 100;
    }
}

@RunWith(PowerMockRunner.class)
@PrepareForTest(UtilityClass.class)
public class MockingStaticMethodTest {

    @Test
    public void testMockingStaticMethod() {

        //模拟整个 UtilityClass 类
        PowerMockito.mockStatic(UtilityClass.class);

        //设置预期返回
        PowerMockito.when(UtilityClass.staticMethod(5)).thenReturn(10);

        //在你的测试代码里, 当 UtilityClass.staticMethod(5) 被调用时, 它现在将返回 10
        int result = UtilityClass.staticMethod(5);

        assertEquals(10, result);

        //最后验证静态方法是否被调用
        PowerMockito.verifyStatic(UtilityClass.class);
        UtilityClass.staticMethod(5);
    }
}

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

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

相关文章

Java SpringBoot基于微信小程序的高速公路服务区充电桩在线预定系统,附源码

博主介绍&#xff1a;✌IT徐师兄、7年大厂程序员经历。全网粉丝15W、csdn博客专家、掘金/华为云//InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3…

自定义类似微信效果Preference

1. 为自定义Preference 添加背景&#xff1a;custom_preference_background.xml <?xml version"1.0" encoding"utf-8"?> <selector xmlns:android"http://schemas.android.com/apk/res/android"><item><shape android:s…

Linux-时间同步服务器

1. (问答题) 一.配置server主机要求如下&#xff1a; 1.server主机的主机名称为 ntp_server.example.com 编写脚本文件 #!/bin/bash hostnamectl hostname ntp_server.example.com cd /etc/NetworkManager/system-connections/ rm -fr * cat > eth0.nmconnection <&…

JSON数据格式讲解与cJSON库的使用

文章目录 写在前面一、安装cJSON二、使用cJSON1、使用的文件2、如何传输数据&#xff1a;**** 三、JSON语法四、cJSON函数讲解1、cJSON结构体 **2、cJSON结构体与字符串之间的转换&#xff08;重要&#xff09;2.1、标题将cJSON结构体转换为字符串(常用)2.2、将字符串转为cJSON…

设计模式—门面模式

定义: 门面模式,也称为外观模式&#xff0c;是一种结构型设计模式。它的主要目的是提供统一的接口来访问子系统中的多个接口&#xff0c;从而简化客户端与复杂子系统之间的交互。 在门面模式中&#xff0c;一个门面类充当中介&#xff0c;为客户端提供一个简化了的访问方式&…

B203-若依框架应用

目录 简介版本RuoYi-fast项目准备新增模块/代码生成 简介 基于SpringBoot的权限管理系统&#xff0c;基于SpringBoot开发的轻量级Java快速开发框架 版本 前后端未分离单应用版本&#xff1a;RuoYi-fast&#xff0c;前后端未分离多模块版本&#xff1a;RuoYi 前后端分离单应用…

Adobe AE(After Effects)2020下载地址及安装教程

Adobe After Effects是一款专业级别的视觉效果和动态图形处理软件&#xff0c;由Adobe Systems开发。它被广泛用于电影、电视节目、广告和其他多媒体项目的制作。 After Effects提供了强大的合成和特效功能&#xff0c;可以让用户创建出令人惊艳的动态图形和视觉效果。用户可以…

逻辑回归模型-逻辑回归算法原理-逻辑回归代码与实现-笔记整合

通过一段时间的学习&#xff0c;总算把逻辑回归模型弄清楚了 《老饼讲解-机器学习》www.bbbdata.com中是讲得最清晰的&#xff0c;结合其它资料&#xff0c;整理一个完整的笔记如下&#xff0c;希望能帮助像我这样入门的新人&#xff0c;快速理解逻辑回归算法原理和逻辑回归实…

代码随想录训练营Day 24|Python|Leetcode|93.复原IP地址, 78.子集,90.子集II

93.复原IP地址 有效 IP 地址 正好由四个整数&#xff08;每个整数位于 0 到 255 之间组成&#xff0c;且不能含有前导 0&#xff09;&#xff0c;整数之间用 . 分隔。 例如&#xff1a;"0.1.2.201" 和 "192.168.1.1" 是 有效 IP 地址&#xff0c;但是 &q…

git clone遇到报错“SSL certificate problem: self signed certificate”

在git clone的时候发现遇到了一个问题&#xff1a; cristDESKTOP-JKRNKSH MINGW64 ~/Desktop $ git clone -b dev https://xxx.xxx.xxx.xxx:3001/crist/AVM_V9M.git Cloning into AVM_V9M... fatal: unable to access https://xxx.xxx.xxx.xxx3001/crist/AVM_V9M.git/: SSL ce…

openGauss学习笔记-264 openGauss性能调优-TPCC性能调优测试指导-BIOS配置

文章目录 openGauss学习笔记-264 openGauss性能调优-TPCC性能调优测试指导-BIOS配置264.1 恢复BIOS出厂设置264.2 修改相关BIOS设置264.3 重启操作系统 openGauss学习笔记-264 openGauss性能调优-TPCC性能调优测试指导-BIOS配置 本章节主要介绍openGauss数据库内核基于鲲鹏服务…

自己的事情自己做:使用 Python Turtle 绘制 Python Logo

以下代码中&#xff0c;将向你展示一个有趣的程序&#xff0c;如何使用 Python Turtle 中绘制 Python Logo。Python 翻译成汉语是蟒蛇的意思&#xff0c;Python 的 Logo 也是两条缠绕在一起的蟒蛇。 import turtlepen turtle.Turtle() turtle.bgcolor("black") pe…

Spring基础篇-快速面试笔记(速成版)

文章目录 1. Spring概述2. 控制反转&#xff08;IoC&#xff09;2.1 Spring声明Bean对象的方式2.2 Spring的Bean容器&#xff1a;BeanFactory2.3 Spring的Bean生命周期2.4 Spring的Bean的注入方式 3. Spring的事件监听器&#xff08;Event Listener&#xff09;3.1 Spring内置事…

开源项目|使用go语言搭建高效的环信 IM Rest接口(附源码)

项目背景 环信 Server SDK 是对环信 IM REST API 的封装&#xff0c; 可以节省服务器端开发者对接环信 API 的时间&#xff0c;只需要配置自己的 App Key 相关信息即可使用。 环信目前提供java和PHP版本的Server SDK&#xff0c;此项目使用go语言对环信 IM REST API 进行封装…

stm32实现hid鼠标

启动CubelMX 选择芯片&#xff08;直接输入stm32f103zet6) 设置时钟 如下图 usb设置 配置usb设备 调试端口设置 配置时钟 项目输出设置 打开工程&#xff08;后记&#xff1a;此工程含有中文不能编译通过) 配置项目 配置调试器 编译无法通过 删除路径中的中文&#xff0c;以及…

facenet人脸检测+人脸识别+性别识别+表情识别+年龄识别的C++部署

文章目录 一. 人脸检测二.人脸识别facenet2.1 训练人脸识别模型2.2 导出ONNX2.3 测试 三.人脸属性&#xff08;性别、年龄、表情、是否戴口罩&#xff09;3.1 训练3.2 导出ONNX3.3 测试 四. 集成应用五、Jetson 部署5.1 NX5.2 NANO 一. 人脸检测 代码位置&#xff1a;1.detect …

Java代码执行顺序

Java代码的执行顺序 后面大量的涉及到了static&#xff0c;我曾经写过一篇static的博客&#xff0c;可以看一眼 我上次写了static的加载顺序&#xff0c;没看过的可以进去看一眼 JavaSE&#xff1a;static关键字详解 ---------------------分割线-------------------------…

✌粤嵌—2024/4/3—合并K个升序链表

代码实现&#xff1a; /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/ struct ListNode* merge(struct ListNode *l1, struct ListNode *l2) {if (l1 NULL) {return l2;}if (l2 NULL) {return l1;}struct Lis…

安装指定版本的ant-design-vue和指定版本的@ant-design/icons-vue 图标组件包

前言&#xff1a; 最近在完成公司的项目时&#xff0c;为了兼容其他的版本&#xff0c;需要安装指定版本的ant-design-vue和ant-design/icons-vue 图标组件包&#xff0c;安装成功之后&#xff0c;分享如下&#xff1a; 安装命令&#xff1a; ant-design-vue&#xff1a; 不…

[移动通讯]【无线感知-P1】[从菲涅尔区模型到CSI模型-2]

前言&#xff1a; 前面我们学习了&#xff1a; 1 只 基于机器学习做无线感知问题&#xff1a;泛化性能差&#xff0c;可解释性差 无法解释为什么能做好,什么时候能做好,什么时候做不好. 可行性 到 可用性&#xff0c;泛化性问题&#xff0c;具体深入的研究。 2 无线感知的理论…