一文说透Springboot单元测试

你好,我是柳岸花开。

一、单元测试说明

1 单元测试的优点与基本原则

一个好的单元测试应该具备以下FIRST 原则和AIR原则中的任何一条:

单元测试的FIRST 规则

Fast 快速原则,测试的速度要比较快,

Independent 独立原则,每个测试用例应该互不影响,不依赖于外部资源。

Repeatable 可重复原则,同一个测试用例多次运行的结果应该是相同的

Self-validating 自我验证原则,单元测试可以自动验证,并不需要手工干预

Thorough 及时原则 单元测试必须即使进行编写,更新,维护。保证测试用例随着业务动态变化

AIR原则

Automatic 自动化原则 单元测试应该是自动运行,自动校验,自动给出结果。

Independent 独立原则 单元测试应该独立运行,吧相互之间无依赖,对外无依赖,多次运行之间无依赖。

Repeatable 可重复原则 单元测试是可重复运动的,每次的结果都稳定可靠。

一个整套完善的单元测试可以保障后续的增添功能时,程序迭代过程中,代码的逻辑正确性。验证程序的输入和输出与最初设计一致。这对后续的集成测试等会提供巨大的帮助。同时也会有利于集成测试的顺利进行。

2 单元测试的粒度应该如何选择

关于单元测试的粒度,可以总结以下几点:

DAO层的单元测试: 对于基本CRUD,可以考虑跳过这一部分单元测试,而一些比较复杂的动态更新、查询等操作,建议用使用H2去做模拟单元测试。

Service层的单元测试:基本上一个Service里面肯定会依赖很多其他的service(此处也建议将成员变量通过构造方法进行注入,以便于单元测试去Mock),此时建议我们将依赖其他service的方法用Mock替代,Service里面的一些数据库的操作也进行Mock。这样可以保证service测试的独立性,不过对于逻辑复杂的方法可能要花很多时间在Mock上面。 如果发现需要Mock的方法过多,那么可能就需要考虑将要测试的方法是不是需要重构。

Controller(API)层的单元测试:主要着重测试HTTP status在 200,400,500 等情况下的异常处理,request及response的转换等。由于其余部分的代码测试都已经在其对应的单元测试覆盖,那么此时可以Mock绝大部分Serivce层中的方法。

一般工具类的单元测试:一些工具类里面包含了比较多的逻辑,所以需要尽可能考虑多种情况下测试用例。

How to write good tests · mockito/mockito Wiki · GitHub

二、引入单元测试组件

pom.xml

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-test</artifactId>

<scope>test</scope>

</dependency>

<build>

<plugins>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-surefire-plugin</artifactId>

</plugin>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-failsafe-plugin</artifactId>

</plugin>

</plugins>

</build>

三、编写单元测试用例

1 JUnit 5 核心API

JUnit 5 官网

JUnit 5 User Guide

2 Mockito

2.1 简介

Mockito 是当前最流行的 单元测试 Mock 框架。采用 Mock 框架,我们可以 虚拟 出一个 外部依赖,降低测试 组件 之间的 耦合度,只注重代码的 流程与结果,真正地实现测试目的。

代码示例


public class ArticleManager {

private ArticleDatabase database;

private ArticleCalculator calculator;

private UserProvider userProvider;

....

}

@ExtendWith({MockitoExtension.class})

public class ArticleManagerTest extends SampleBaseTestCase 
{

@Mock

private ArticleCalculator calculator;

// note the mock name attribute

@Mock(name = "database")

private ArticleDatabase dbMock;

@Spy

private UserProvider userProvider = new ConsumerUserProvider();

@InjectMocks

private ArticleManager manager;

@Test

public void shouldDoSomething() {

//mock method behave for @Mock Object

when(calculator.someMethod(anyInt())).thenReturn("A value");

when(dbMock.someMethod(anyInt())).thenReturn("A value");

//mock method behave for @Spy Object

doReturn("foo").when(userProvider).getById(100001);

//call target test method 并断言执行结果

assertEquals(1,manager.initiateArticle());

// 验证Mock的方法被调用到了

verify(userProvider).getById(100001);

}

}

官方说明及文档:

Mockito framework site

doc:Mockito - mockito-core 5.6.0 javadoc

2.2 核心API

1 Mockito.mock() / @Mock: 创建 mock 对象


//Let's import Mockito statically so that the code looks clearer

import static org.mockito.Mockito.*;

//mock creation

List mockedList = mock(List.class);

//using mock object

mockedList.add("one");

mockedList.clear();

//verification

verify(mockedList).add("one");

verify(mockedList).clear();

**推荐使用@Mock注解方式**

public class ArticleManagerTest {

@Mock

private ArticleCalculator calculator;

@Mock

private ArticleDatabase database;

@Mock

private UserProvider userProvider;

}

2 Mockito.when() / BDDMockito.given() mock 方法结果

具体用法,看这个两个类上的注释

3 Mockito.spy() / @Spy 仿造真实对象的部分方法

具体说明及用法看 Mockito.spy() 方法的注释

4 @InjectMocks 将 @Moc @Spy 仿造的对象注入到被测试对象

具体用法,看InjectMocks类上的注释

注意:

有些依赖没法用@InjectMocks来自动注入,可以通过引入ReflectionTestUtils,解决依赖注入的问题。

ReflectionTestUtils.setField(controller,"service",service);

5 Mockito.verify() 验证仿造行为被执行

verify系列方法注释

3 spring test

Testing :: Spring Framework

为基于spring框架开发的应用的测试提供了一系列工具封装,让我们能更简便编写测试用例。

3.1 Unit Testing

Unit Testing :: Spring Framework

真正的单元测试通常运行得非常快,因为不需要设置运行时基础设施。强调真正的单元测试作为开发方法的一部分可以提高您的生产力。您可能不需要测试章节的这一部分来帮助您为基于ioc的应用程序编写有效的单元测试。然而,对于某些单元测试场景,Spring框架提供了模拟对象和测试支持类,这些将在本章中描述

Mock Objects

Spring包含许多专门用于mock的包,模拟这些对象:

Environment

JNDI

Servlet API

Spring Web Reactive

测试支持类

AopTestUtils 用于获取被代理对象

ReflectionTestUtils 用于对 非 public的属性等设置值

TestSocketUtils is a simple utility for finding available TCP ports on localhost for use in integration testing scenarios.

3.2 Integration Testing

Spring集成测试模块的目标

Spring的集成测试支持有以下主要目标:

To manage Spring IoC container caching between tests.

To provide Dependency Injection of test fixture instances.

To provide transaction management appropriate to integration testing.

To supply Spring-specific base classes that assist developers in writing integration tests.

管理测试之间的Spring IoC容器缓存。

提供测试fixture实例的依赖注入。

提供适合集成测试的事务管理。

提供特定于spring的基类,帮助开发人员编写集成测试。

Context Management and Caching

Spring TestContext框架提供了Spring ApplicationContext实例和WebApplicationContext实例的一致加载,以及这些上下文的缓存。对加载上下文的缓存支持很重要,因为启动时间可能成为一个问题。

Dependency Injection of Test Fixtures 测试装置的依赖注入

当TestContext框架加载应用程序上下文时,它可以通过使用依赖注入选择性地配置测试类的实例。这提供了一种方便的机制,可以通过使用应用程序上下文中的预配置bean来设置测试fixture。这里的一个强大的好处是,您可以跨各种测试场景重用应用程序上下文(例如,用于配置spring管理的对象图、事务代理、数据源实例等),从而避免了为单个测试用例复制复杂测试fixture设置的需要。

Transaction Management

在访问真实数据库的测试中,一个常见的问题是它们对持久性存储状态的影响。即使在使用开发数据库时,对状态的更改也可能影响将来的测试。此外,许多操作(例如插入或修改持久数据)不能在事务之外执行(或验证)。

TestContext框架解决了这个问题。默认情况下,框架为每个测试创建并回滚一个事务。您可以编写可以假定存在事务的代码。如果在测试中调用事务代理对象,则根据其配置的事务语义,它们的行为正确。另外,如果一个测试方法在为测试管理的事务中运行时删除了所选表的内容,那么该事务在默认情况下回滚,并且数据库返回到执行测试之前的状态。事务性支持是通过使用在测试的应用程序上下文中定义的PlatformTransactionManager bean提供给测试的。

如果您想要提交事务(不常见,但在您想要填充或修改数据库的特定测试时偶尔有用),您可以告诉TestContext框架使用@Commit注释导致事务提交,而不是回滚。

3.3 JDBC Testing Support

JDBC 测试支持提供了如下两种:

JdbcTestUtils工具类

JdbcTestUtils provides the following static utility methods.

countRowsInTable(..): Counts the number of rows in the given table.

countRowsInTableWhere(..): Counts the number of rows in the given table by using the provided WHERE clause.

deleteFromTables(..): Deletes all rows from the specified tables.

deleteFromTableWhere(..): Deletes rows from the given table by using the provided WHERE clause.

dropTables(..): Drops the specified tables.

Embedded Databases

The spring-jdbc module provides support for configuring and launching an embedded database, which you can use in integration tests that interact with a database. For details, see Embedded Database Support and Testing Data Access Logic with an Embedded Database.

👇关注我,下期了解👇 ​ SpringMVC源码 ​ ​ alt ​ ​ 回复 222,获取Java面试题合集 ​ 关于我 ​ 一枚爱折腾的Java程序猿,专注Spring干货。把路上的问题记录下来,帮助那些和我一样的人。 ​ 好奇心强,喜欢并深入研究古天文。 ​ 崇尚 个人系统创建,做一些时间越长越有价值的事情。思考 把时间留下来 又 每刻都是新的。

本文由 mdnice 多平台发布

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

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

相关文章

【Springboot】新增profile环境配置应用启动失败

RT 最近接手了一个新的项目&#xff0c;为了不污染别人的环境&#xff0c;我新增了一个自己的环境配置。结果&#xff0c;在启动的时候总是失败&#xff0c;就算是反复mvn clean install也是无效。 问题现象 卡住无法进行下一步 解决思路 由于之前都是能启动的&#xff0c…

随机过程基础:3.平稳过程(2)

平稳过程是指随机过程的统计特性&#xff08;如均值、方差、协方差等&#xff09;不随时间变化。我们可以在时间域或频率域上研究其性质。以下是对平稳过程的协方差函数和功率谱密度的详细讨论。 一、协方差函数 协方差函数就像是描述两个随机变量之间关系的一种“尺子”。想象…

LLM之Prompt(四)| OpenAI、微软发布Prompt技术报告

摘要 生成式人工智能 &#xff08;GenAI&#xff09; 系统正越来越多地部署在各行各业和研究机构。开发人员和用户通过使用提示或提示工程与这些系统进行交互。虽然提示是一个广泛提及且被研究的概念&#xff0c;但由于该领域的新生&#xff0c;存在相互矛盾的术语和对构成提示…

API接口的概念和接口测试的概念

一、什么是接口测试 接口测试是项目测试的一部分&#xff0c;顾名思义&#xff0c;它测试的主要对象是接口&#xff0c;是测试系统组件间接口的一种测试。接口测试主要用于检测外部系统与所测系统之间以及内部各系统之间的交互点。测试的重点是检查数据交互、传递、和控制管理过…

三级_网络技术_17_交换机及其配置

1.下面是一台三层交换机的部分路由表信息。根据表中的路由信息&#xff0c;以下描述错误的是()。 此设备启用了OSPF动态路由协议&#xff0c;并学到了E1和E2两种类型的OSPF外部路由 比设备通过动态路由协议得到缺省路由&#xff0c;下一跳是设备的TenGigabitEthernet1/15接口 …

聚类分析方法(三)

目录 五、聚类的质量评价&#xff08;一&#xff09;簇的数目估计&#xff08;二&#xff09;外部质量评价&#xff08;三&#xff09;内部质量评价 六、离群点挖掘&#xff08;一&#xff09;相关问题概述&#xff08;二&#xff09;基于距离的方法&#xff08;三&#xff09;…

泛微E-Cology WorkflowServiceXml SQL注入漏洞复现(QVD-2024-26136)

0x01 产品简介 泛微e-cology是一款由泛微网络科技开发的协同管理平台,支持人力资源、财务、行政等多功能管理和移动办公。 0x02 漏洞概述 2024年7月,泛微官方发布了新补丁,修复了一处SQL注入漏洞。经分析,攻击者无需认证即可利用该漏洞,建议受影响的客户尽快修复漏洞。…

springboot 适配ARM 架构

下载对应的maven https://hub.docker.com/_/maven/tags?page&page_size&ordering&name3.5.3-alpinedocker pull maven:3.5.3-alpinesha256:4c4e266aacf8ea6976b52df8467134b9f628cfed347c2f6aaf9e6aff832f7c45 2、下载对应的jdk https://hub.docker.com/_/o…

《后端程序员 · Nacos 常见配置 · 第一弹》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…

C++ 类和对象(A)

一、类与对象的初步认识 1.类是对象的抽象&#xff0c;而对象是类的具体实例。 类是抽象的&#xff0c;不占用内存&#xff1b;而对象是具体的&#xff0c;占用存储空间。 2.面向过程与面向对象 C语言是面向过程的&#xff0c;关注的是过程中的数据与方法。 C是面向对象的&…

3D打印技巧

blender建模设置 避免破面 插件&#xff1a;3D打印 其中 错误连续边bad contig. edges指的是同一条线两侧法向不同&#xff0c;解决方案&#xff1a;shiftn 零面zero face指有两个面重叠&#xff0c;解决方案&#xff1a;按距离合并 非平面non flat face指四边形面的四个顶…

Django select_related()方法

select_related()的作用 select_related()是Django ORM&#xff08;对象关系映射&#xff09;中的一种查询优化方法&#xff0c;主要用于减少数据库查询次数&#xff0c;提高查询效率。当你在查询一个模型实例时&#xff0c;如果这个实例有ForeignKey关联到其他模型&#xff0…

【.NET全栈】ASP.NET开发web应用——ASP.NET中的样式、主题和母版页

文章目录 前言一、在ASP.NET中应用CSS样式1、创建CSS样式&#xff08;1&#xff09;内联样式&#xff08;2&#xff09;内部样式表&#xff08;3&#xff09;外部样式表 2、应用CSS样式&#xff08;1&#xff09;菜鸟教程-简单例子&#xff08;2&#xff09;菜鸟教程-用户界面&…

2024-07-12 Unity AI状态机1 —— 框架介绍

文章目录 1 有限状态机2 状态机实现框架2.1 StateMachine2.2 BaseState2.3 ...State2.4 IAIObject 3 框架类图 本文章参考 B 站唐老狮 2023 年直播内容。点击前往唐老狮 B 站主页。 1 有限状态机 ​ 有限状态机&#xff08;Finite - State Machine&#xff0c;FSM&#xff09…

【Diffusion学习】【生成式AI】Diffusion Model 原理剖析 (2/4) (optional)【公式推导】

文章目录 影像生成模型本质上的共同目标【拟合分布】Maximum Likelihood Estimation VAE 影像生成模型本质上的共同目标【拟合分布】 Maximum Likelihood Estimation VAE

# Redis 入门到精通(四)-- linux 环境安装 redis

Redis 入门到精通&#xff08;四&#xff09;-- linux 环境安装 redis 一、linux 环境安装 redis – 基于 Linux 安装 redis 1、基于 Center 0S7 或者 unbunt-18.04 安装 Redis 1&#xff09;下载安装包wget http://download.redis.io/releases/redis-?.?.?.tar.gz 如&…

夏令营入门组day4

一. 题目 二. 思路 &#xff08;1&#xff09;B要先去和A回合&#xff0c;因为B只能将红染成蓝&#xff0c;不能直接将白染成蓝&#xff0c;所以B必须走A走过的路才有效。 &#xff08;2&#xff09;答案分为两部分&#xff0c;去和A回合的最短距离 以回合点为根节点&#xf…

FPGA上板项目(二)——PLL测试

目录 实验内容实验原理实验步骤实验结果 实验内容 将差分时钟信号转化为 192MHz 时钟信号作为输出。 实验原理 PLL&#xff0c;即锁相环&#xff0c;一种反馈控制电路&#xff0c;具有时钟倍频、分频、相位偏移和可编程占空比的功能。 实验步骤 添加 clocking wizard IP核&…

Gitlab CI/CD --- use a sample CI/CD template

0 Preface/Foreword Pipeline, job, stage的关系如下描述&#xff1a; A pipeline is composed of independent jobs that run scripts, grouped into stages. Stages run in sequential order, but jobs within stages run in parallel. 关键信息&#xff1a; pipeline由独…

Ubuntu 磁盘扩容

1.下载工具 sudo apt-get install gparted 2.调整大小