Java 单元测试模拟框架-Mockito 的介绍

news2024/12/27 10:23:32

Mockito 是什么

在这里插入图片描述

Mockito 是一个用于单元测试的模拟框架,基于它可以使用简洁易用的API编写出色的测试。
Mockito 允许开发人员创建和管理模拟对象(mock objects),以便在测试过程中替换那些不容易构造或获取的对象。

Mockito的基本概念

  1. Mock对象:在调试期间用来作为真实对象的替代品。通过模拟对象,可以模拟外部依赖、交互行为等,从而使测试更加独立和可控。
  2. Mock测试:在测试过程中,对那些不容易构建的对象用一个虚拟对象来代替测试的方法就叫mock测试。
  3. Stub:存根,即为mock对象的方法指定返回值(可抛出异常)。
  4. Verify:行为验证,验证指定方法调用情况(是否被调用,调用次数等)。

Mockito的主要功能

  1. 模拟方法行为:Mockito允许对模拟对象的方法进行stubbing,即定义当调用某个方法时应该返回的值或抛出的异常。
  2. 验证交互行为:Mockito提供了丰富的API来验证模拟对象的交互行为,例如方法是否被调用、调用次数、参数匹配等。
  3. 参数匹配器:Mockito提供了参数匹配器,允许在验证方法调用时使用通配符或自定义匹配规则。
  4. 部分模拟:使用@Spy注解可以创建一个部分模拟对象,允许选择性地模拟对象中的某些方法。

选择Mockito作为模拟框架的原因

  • StackOverflow庞大的社区将Mockito评为Java的最佳模拟框架
  • 在2013年末对30,000个GitHub项目进行分析时,Mockito在所有库(不仅仅是测试工具)中位列前10名Java库。尽管Mockito在主报告中排名第九,但mockito-core和mockito-all是同一工具,因此Mockito的实际排名是第四,超过了诸如Guava或Spring等著名工具。将此研究视为Mockito每天对用Java编写的单元测试产生巨大影响的指标。
  • 行为驱动开发(BDD)的创始人Dan North在2008年写道:“我们在主要会议期间决定使用JUnit 4和Mockito,因为我们认为它们是Java中TDD和模拟的未来。”

基于Maven 如何使用Mockito:

Mockito的使用步骤

  1. 添加依赖:在项目的构建文件(如Maven的pom.xml或Gradle的build.gradle)中添加Mockito的依赖。
  2. 设置测试类:使用@RunWith(MockitoJUnitRunner.class)注解测试类,或使用MockitoAnnotations.initMocks(this)在@Before方法中初始化模拟对象。
  3. 创建模拟对象:使用@Mock注解创建模拟对象,或使用Mockito.mock(Class)方法。
  4. 设置模拟行为:使用when(…).thenReturn(…)或doReturn(…).when(…)等方法设置模拟对象的行为。
  5. 编写测试方法:在测试方法中调用被测对象的方法,并使用verify(…)等方法验证交互行为。
  6. 运行测试:使用JUnit运行测试,并查看测试结果。

Mockito当前的最新版本是 5.14.2,在pom.xml中导入之后就可以开始使用了。

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>5.14.2</version>
</dependency>

使用场景1: 验证交互行为, 模拟方法是否被调用了?

创建Mock对象, 验证对象的方法是否被调用了。

/**
 * Copyright (C)  Oscar Chen(XM):
 * 
 * Date: 2024-12-01
 * Author: XM
 */
package com.osxm.test.mock;

import static org.mockito.Mockito.*; // 导入Mockito的静态方法

import java.util.List;

import org.junit.jupiter.api.Test;

public class MockitoTest {

    @Test
    public void mockitoDemo() {

        // 创建mock对象
        List mockedList = mock(List.class); // 创建一个List接口的mock对象
        // 或者在Mockito 4.10.0及以上版本中,使用更简洁的方式
        // List mockedList = mock();

        // 使用mock对象,它不会抛出任何“意外交互”异常
        mockedList.add("one");
        mockedList.clear();

        // 选择性、明确且高度可读的验证
        verify(mockedList).add("one"); // 验证mock对象调用了add方法并传入了"one"
        verify(mockedList).clear(); // 验证mock对象调用了clear方法

    }

}

使用场景2:模拟方法调用

模拟方法执行返回的结果。

    @Test
    public void mockMethodCall(){
        // 不仅可以模拟接口,还可以模拟具体类
        LinkedList mockedList = mock(LinkedList.class); // 创建一个LinkedList类的mock对象
        // 或者在Mockito 4.10.0及以上版本中,使用更简洁的方式
        // LinkedList mockedList = mock();

        // 在实际执行之前进行模拟(stubbing)
        when(mockedList.get(0)).thenReturn("first"); // 当调用mockedList的get(0)方法时,返回"first"

        // 以下打印输出为"first"
        System.out.println(mockedList.get(0));

        // 以下打印输出为"null",因为get(999)方法没有被模拟
        System.out.println(mockedList.get(999));
    }

主要参考

  • mock()方法,或者 @Mock注解: 创建模拟对象
  • when()/given() 指定模拟对象的行为
  • spy()/@Spy 部门模拟, 真实方法会呼叫并且可以被验证和存根
  • @InjectMocks:自动注入用@Spy或@Mock注解的模拟/间谍字段
  • verify() : 检查方法是否使用给定参数被调用
    • 可以使用灵活的参数匹配,例如通过any()匹配任意表达式
    • 或者使用@Captor捕获被调用的参数
  • 可以使用BDDMockito进行行为驱动开发语法

Mockito的常用注解

  1. @RunWith:用于指定JUnit测试的运行器。对于Mockito,通常使用@RunWith(MockitoJUnitRunner.class)来运行测试。
  2. @Mock:用于创建模拟对象。
  3. @InjectMocks:用于将模拟对象注入到被测对象中。
  4. @Spy:用于创建部分模拟对象。

使用注意

不要干什么:

  • 不要模拟不属于你的类型
  • 不要模拟值对象
  • 不要模拟一切
  • 对测试表现一些爱心

不能干什么:

  1. 不能Mock静态方法:Mockito不支持对静态方法进行mock。
  2. 不能Mock private方法:Mockito不支持对private方法进行mock。
  3. 不能Mock final class:Mockito不支持对final类进行mock。

Mockito的集成与扩展

  1. 与JUnit集成:Mockito可以与JUnit无缝集成,使用@RunWith(MockitoJUnitRunner.class)即可。
  2. 与Spring集成:在Spring Boot项目中,可以使用@MockBean注解来模拟Spring上下文中的对象。
  3. 扩展功能:Mockito提供了丰富的扩展功能,如Mockito-inline用于支持内联Mocks的创建和使用等。

参考

  • 官方站点 http://site.mockito.org/#intro

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

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

相关文章

分享一款 Vue 图片编辑插件 (推荐)

&#x1f4a5;本篇文章给大家分享一款强大到没朋友的Vue图片编辑插件&#xff0c;可以对图片进行旋转、缩放、裁剪、涂鸦、标注、添加文本等&#xff0c;快来试试并收藏吧&#xff01;&#x1f495; 这是一款对图片进行旋转、缩放、裁剪、涂鸦、标注、添加文本在线处理的图片处…

在基于控制器的 API 和最小 API 之间进行选择

文章目录 ASP.NET Core 支持两种创建 API 的方法&#xff1a;基于控制器的方法和最小 API。 API 项目中的控制器是派生自 ControllerBase 的类。 最小 API 在 Lambda 或方法中使用逻辑处理程序定义终结点。 本文解释了这两种方法之间的差异。 最小 API 的设计默认隐藏了主机类…

【UVM】phase机制

Phase的种类 funcion phase 不消耗仿真时间 八种&#xff08;图中白色背景&#xff09; task phase 消耗仿真时间 一种&#xff08;图中灰色背景&#xff09;&#xff0c;run_phase又可以细分为十二种 Phase的功能 bulid_phase&#xff1a;uvm_component类的实例化&…

《装甲车内气体检测“神器”:上海松柏 K-5S 电化学传感器模组详解》

《装甲车内气体检测“神器”:上海松柏 K-5S 电化学传感器模组详解》 一、引言二、K-5S 电化学传感器模组概述&#xff08;一&#xff09;产品简介&#xff08;二&#xff09;产品特点&#xff08;三&#xff09;产品适用场景 三、电化学传感器原理及优点&#xff08;一&#xf…

【Linux课程学习】:文件第二弹---理解一切皆文件,缓存区

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;Linux课程学习 &#x1f337;追光的人&#xff0c;终会万丈光芒 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 Linux学习笔记&#xff1a; https://blog.csdn.net/d…

汽车控制软件下载移动管家手机控车一键启动app

移动管家手机控制汽车系统是一款实现车辆远程智能控制的应用程序‌。通过下载并安装特定的APP&#xff0c;用户可以轻松实现以下功能&#xff1a;‌远程启动与熄火‌&#xff1a;无论身处何地&#xff0c;只要有网络&#xff0c;即可远程启动或熄火车辆&#xff0c;提前预冷或预…

匿名发帖/匿名论坛功能设计与实现(编辑发帖部分)

前言 还是之前的音乐系统&#xff0c;首页一直是没想好写些什么&#xff0c;想写一个基于数据分析筛选的歌曲推荐功能&#xff0c;但是目前技术选型没太有考究等以后再实现吧&#xff0c;昨天突然想到可以把首页设计成前40%页面是歌曲推荐后面接下来就是一段匿名论坛功能&…

微信小程序 城市点击后跳转 并首页显示被点击城市

在微信小程序中&#xff0c;渲染出城市列表后&#xff0c;如何点击城市&#xff0c;就跳转回到首页&#xff0c;并在首页显示所点击的城市呢&#xff1f; 目录 一、定义点击城市的事件 二、首页的处理 首页&#xff1a;点击成都市会跳转到城市列表 城市列表&#xff1a;点击…

DOM,事件监听和VUE入门

四个事件、 JS模块化 VUE入门 Ajax VUE总结

Python学习笔记(5)Python的创建型设计模式

创建型设计模式&#xff08;Creational Design Patterns&#xff09;&#xff0c;主要关注对象的创建机制。这类模式可以使得系统更加独立于如何创建、组合和表示其对象。通过将这些职责分离出来&#xff0c;创建型设计模式有助于提高代码的灵活性和复用性。 本书的范例代码已经…

云备份实战项目

文章目录 前言一、整体项目简介二、服务端环境及功能简介三、 客户端环境及功能简介四、服务端文件管理类的实现1. 获取文件大小&#xff0c;最后一次修改时间&#xff0c;最后一次访问时间&#xff0c;文件名称&#xff0c;以及文件内容的读写等功能2. 判断文件是否存在&#…

Java有关数组的相关问题

Java中的栈和堆的含义 栈 存储局部变量&#xff1a;栈主要用于存储方法中的局部变量&#xff0c;包括基本数据类型&#xff08;int、double、boolean等&#xff09;和对象的引用&#xff08;不包含对象本身&#xff09;。 遵循后进先出原则&#xff1a;当一个方法被调用时&…

使用Dify与BGE-M3搭建RAG(检索增强生成)应用-改进一,使用工作流代替Agnet

文章目录 前言Agent vs 工作流编写工作流 前言 在上一篇中&#xff0c;我们实现了一个基本的基于Dify的RAG的示范。 使用Dify与BGE-M3搭建RAG&#xff08;检索增强生成&#xff09;应用 这个效果确实很差。 我们一起来看看&#xff0c;该怎么改进。 今天我们就尝试一下&…

Python语法基础(四)

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 高阶函数之map 高阶函数就是说&#xff0c;A函数作为B函数的参数&#xff0c;B函数就是高阶函数 map&#xff1a;映射 map(func,iterable) 这个是map的基本语法&#xff0c;…

Python毕业设计选题:基于django+vue的智慧社区可视化平台的设计与实现+spider

开发语言&#xff1a;Python框架&#xff1a;djangoPython版本&#xff1a;python3.7.7数据库&#xff1a;mysql 5.7数据库工具&#xff1a;Navicat11开发软件&#xff1a;PyCharm 系统展示 管理员登录 管理员功能界面 养老机构管理 业主管理 社区安防管理 社区设施管理 车位…

Ubuntu环境中RocketMQ安装教程

参考教程 https://blog.csdn.net/weixin_56219549/article/details/126143231 1、安装JDK&#xff0c;并配置环境变量&#xff08;略&#xff09; 2、下载RocketMQ安装包 RocketMQ下载地址&#xff0c;选择二进制包下载 unzip rocketmq-all-5.0.0-ALPHA-bin-release.zip 使…

【SSM】mybatis的增删改查

目录 代理Dao方式的增删改查 1. 创建项目 $$1. 在sql.xml里增加日志代码以及user的mapper资源。 $$ 2. 在usermapper里引入接口。 $$3. 在测试类中引入以下代码&#xff0c;并修改其中名字。 $$ 4. 实例对象User.java里属性要与表中列严格对应。 2. 查询 1>. 查询所有 …

【C++习题】23.二分查找算法_寻找旋转排序数组中的最小值

文章目录 题目链接&#xff1a;题目描述&#xff1a;解法C 算法代码&#xff1a;图解 题目链接&#xff1a; 153. 寻找旋转排序数组中的最小值 题目描述&#xff1a; 解法 暴力解法&#xff1a;O(n) 从前往后找数组中的最小值。 二分算法&#xff1a;O(logn) 先找二段性 因为这…

Linux笔记---进程:进程终止

1. 进程终止概念与分类 进程终止是指一个正在运行的进程结束其执行的操作。以下是一些常见的导致进程终止的情况&#xff1a; 一、正常终止 完成任务当进程完成了它被设计要执行的任务后&#xff0c;就会正常终止。收到特定信号在操作系统中&#xff0c;进程可能会收到来自操作…

立创庐山派 K230 RTSP 推流

立创庐山派使用的是K230芯片&#xff0c;按照教程刷了canmv固件&#xff0c;下载canmv ide&#xff0c;使用嘉楠社区的rtsp和wlan例程&#xff0c;修改成连接wifi以及RTSP推流例程 # Description: This example demonstrates how to stream video and audio to the network us…