单元测试实战(四)MyBatis-Plus 的测试

为鼓励单元测试,特分门别类示例各种组件的测试代码并进行解说,供开发人员参考。

本文中的测试均基于JUnit5。

单元测试实战(一)Controller 的测试

单元测试实战(二)Service 的测试    

单元测试实战(三)JPA 的测试

单元测试实战(四)MyBatis-Plus 的测试

单元测试实战(五)普通类的测试

单元测试实战(六)其它

概述

MyBatis Plus组件表现为Mapper对象(我们将不涉及IService的测试)。使用MyBatis/MyBatis-Plus的项目,往往有很多自写的SQL需要测试。

MyBatis Plus有专门的@MyBatisPlusTest注解,是苞米豆提供的功能,它是有Spring上下文的,使用JUnit的SpringExtension扩展类。与@DataJpaTest一样,它会在测试时自动将数据源替换为内存数据库的。

在本章的示例中,我们将展示一种使用SQL脚本来准备测试数据的方法。

断言应主要检查数据存取行为是否符合预期。

依赖

除依赖Spring自带测试框架外,还需要苞米豆的测试包以及内存数据库:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope>
</dependency>
<dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-api</artifactId><scope>test</scope>
</dependency>
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter-test</artifactId><version>3.5.3.2</version><scope>test</scope>
</dependency>
<dependency><groupId>com.h2database</groupId><artifactId>h2</artifactId><scope>test</scope>
</dependency>

注意:mybatis-plus-boot-starter-test的3.5.2版本支持Spring Boot 2,3.5.3及以上支持Spring Boot 3。

示例

由于篇幅的关系,本章中我们将拿出一个Mapper方法作为示例。

以下为xml实现的一个查询方法:

<select id="selectPermissionCodesByUser" resultType="java.lang.String">SELECT p.codeFROM sys_auth_user_role urJOIN sys_auth_role_permission rp ON rp.role_id=ur.role_idJOIN sys_auth_permission p ON p.id=rp.permission_idWHERE p.type=2 AND ur.user_code=#{userCode} AND ur.asset_type=#{assetType} AND ur.asset_id=#{assetId}<if test="pkOrg != null">UNION DISTINCTSELECT p.codeFROM sys_auth_user_org uoJOIN sys_auth_role_permission rp ON rp.role_id=uo.role_idJOIN sys_auth_permission p ON p.id=rp.permission_idWHERE p.type=2 AND uo.user_code=#{userCode} AND uo.pk_org=#{pkOrg}</if>
</select>

以下为该查询的代理接口:

public interface SysAuthPermissionMapper extends BaseMapper<SysAuthPermission> {...Set<String> selectPermissionCodesByUser(@Param("userCode") String userCode,@Param("assetType") int assetType,@Param("assetId") long assetId,@Param("pkOrg") String pkOrg);...
}

以下是该查询方法的测试类:

package com.aaa.sdk.rbac.mybatis.database.mapper;import com.baomidou.mybatisplus.test.autoconfigure.MybatisPlusTest;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jdbc.datasource.init.ScriptUtils;
import org.springframework.test.context.TestPropertySource;import javax.sql.DataSource;
import java.sql.Connection;
import java.util.Set;import static org.assertj.core.api.Assertions.assertThat;@MybatisPlusTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@TestPropertySource(properties = {"spring.datasource.driver-class-name=org.h2.Driver","spring.datasource.url=jdbc:h2:mem:aaa_rbac_test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MODE=MySQL;DATABASE_TO_LOWER=TRUE","spring.datasource.username=sa"
})
class SysAuthPermissionMapperTest {@Autowiredprivate SysAuthPermissionMapper mapper;@BeforeAllstatic void setupClass(@Autowired DataSource dataSource) throws Exception {try (Connection conn = dataSource.getConnection()) {ScriptUtils.executeSqlScript(conn, new ClassPathResource("/sql/test_schema.sql"));ScriptUtils.executeSqlScript(conn, new ClassPathResource("/sql/test_data.sql"));}}@Testvoid testSelectPermissionCodesByUser() {Set<String> permissions = mapper.selectPermissionCodesByUser("wangfei012", 1, 1, "0001A410000000A3I0V2");assertThat(permissions).hasSize(4);}@Testvoid testSelectPermissionCodesByUser_emptyPkOrg() {Set<String> permissions = mapper.selectPermissionCodesByUser("wangfei012", 1, 1, "");assertThat(permissions).hasSize(3);}@Testvoid testSelectPermissionCodesByUser_invalidUser() {Set<String> permissions = mapper.selectPermissionCodesByUser("nobody", 1, 1, "0001A410000000A3I0V2");assertThat(permissions).hasSize(0);}
}

测试类说明:

第18行,我们使用了@MyBatisPlusTest类注解。

第19行,为了H2数据库兼容MySQL语法,我们关闭了数据源的自动替换,选择用20-24行的代码来覆盖默认的数据源。

第28行,我们将代理接口注入测试类。

31行的setupClass方法会在所有测试方法执行之前执行一次,准备数据。这里我们用了Spring自带的ScriptUtils实用程序;其中sql脚本是在test目录下的resources文件夹;测试目录结构如下图:

上图中,MockApplication与测试在同一个包内,用来控制Spring上下文范围,以免启动真实的SpringBootApplication;它的代码如下(注意里面有个@MapperScan,用来发现当前包里的MyBatis mapper):

package com.aaa.sdk.rbac.mybatis.database.mapper;import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
@MapperScan(basePackages = {"com.aaa.sdk.rbac.mybatis.database.mapper"})
public class MockApplication {
}

以下继续测试类的说明:

从第38行开始,是selectPermissionCodesByUser方法的三个测试用例。

testSelectPermissionCodesByUser测试正常流程,包括全部4个正常参数。按照设计和测试数据,它应该取出4个结果。

testSelectPermissionCodesByUser_emptyPkOrg测试传入的pkOrg参数为空时的场景,覆盖的是xml文件中<if test="pkOrg != null">不满足的分支。按照设计和测试数据,它应该取出3个结果。

testSelectPermissionCodesByUser_invalidUser则是一个负面测试,测试当传入的userCode非法时的场景;它应该不返回任何结果。

与JPA的测试一样,测试类中没有Mock对象,因此也就不存在given - when - then三段式结构。(DAO对象没有更底层的依赖,因此不需注入Mock,这也使得它们看上去更像是一种与数据库的集成测试。)

总结

使用@MybatisPlusTest。

为了兼容MySQL语法而使用@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE),并用@TestPropertySource订制数据源属性。注意:兼容只是部分兼容,并非完全兼容。

使用@BeforeAll方法结合Spring自带的ScriptUtils准备测试数据。

MockApplication里加@MapperScan。

示例中,我们没有在每个方法之前重置测试数据,这是因为我们只测了查询方法吗?不。在DAO的测试中,不管是@MyBatisPlusTest还是@DataJpaTest,都带有@Transactional元注解,它们会在测试方法执行结束后自动回滚。

MyBatis-Plus 有所谓的 Lambda Query,可链式组合查询。我们不建议在Service的实现类里直接使用它;应该将其封装到DAO/Repository层的方法里,这样就方便mock这个封装好的方法的行为,避免直接mock链式组合查询行为。如果实在要mock链式组合查询行为,可以参考这篇和这篇。 

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

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

相关文章

鸿蒙开发|开启鸿蒙开发之旅-发工具下载安装、项目创建和预览

文章目录 一、鸿蒙开发使用语言二、下载开发工具三、安装开发工具四、新建项目五、项目启动 一、鸿蒙开发使用语言 鸿蒙OS开发支持多种编程语言&#xff0c;开发者可以根据自身技术背景和项目需求选择合适的语言进行开发。目前鸿蒙OS主要支持以下几种语言&#xff1a; Java&am…

掌握未来技术趋势,Python编程引领人工智能时代

掌握未来技术趋势&#xff0c;Python编程引领人工智能时代 摘要&#xff1a;Python作为一种高级编程语言&#xff0c;在人工智能领域中扮演着越来越重要的角色。本文将通过介绍Python编程的特点、应用场景及发展前景&#xff0c;展望Python未来的发展趋势&#xff0c;并结合代…

HarmonyOS真机调试报错:INSTALL_PARSE_FAILED_USESDK_ERROR处理

文章目录 1、 新建应用时选择与自己真机匹配的sdk版本2、 根据报错提示连接打开处理方案3、查询真机版本对应的**compileSdkVersion** 和 **compatibleSdkVersion** 提示3.1版本之后和3.1版本之前的不同命令&#xff08;此处为3.0版本&#xff09;4、根据查询修改参数5、连接成…

13.真刀实枪做项目---博客系统(页面设计)

文章目录 1.预期效果1.1博客列表页效果1.2博客详情页效果1.3博客登陆页效果1.4博客编辑页效果 2.实现博客列表页2.1实现导航栏2.2实现版心2.3实现个人信息2.4实现博客列表2.5博客列表页完整代码 3.实现博客正文页3.1引入导航栏3.2引入版心3.3引入个人信息3.4实现博客正文3.5博客…

Django模型层

模型层 与数据库相关的&#xff0c;用于定义数据模型和数据库表结构。 在Django应用程序中&#xff0c;模型层是数据库和应用程序之间的接口&#xff0c;它负责处理所有与数据库相关的操作&#xff0c;例如创建、读取、更新和删除记录。Django的模型层还提供了一些高级功能 首…

【机器学习Python实战】logistic回归

&#x1f680;个人主页&#xff1a;为梦而生~ 关注我一起学习吧&#xff01; &#x1f4a1;专栏&#xff1a;机器学习python实战 欢迎订阅&#xff01;后面的内容会越来越有意思~ ⭐内容说明&#xff1a;本专栏主要针对机器学习专栏的基础内容进行python的实现&#xff0c;部分…

PlantUML基础使用教程

环境搭建 IDEA插件下载 打开IEDA系列IDE&#xff0c;从FIle–>Settings–>Plugins–>Marketplace 进入到插件下载界面&#xff0c;搜索PlantUML&#xff0c;安装PlantUML Integration和PlantUML Parser两个插件&#xff0c;并重启IDE 安装和配置Graphviz 进入官网…

《视觉SLAM十四讲》-- 后端 2

文章目录 09 后端 29.1 滑动窗口滤波和优化9.1.1 实际环境下的 BA 结构9.1.2 滑动窗口法 9.2 位姿图9.2.1 位姿图的意义9.2.2 位姿图优化 09 后端 2 9.1 滑动窗口滤波和优化 9.1.1 实际环境下的 BA 结构 由于计算机算力的限制&#xff0c;我们必须控制 BA 的规模&#xff0c…

进程程序替换与exec系统调用

进程程序替换 进程程序替换是指将一个正在运行的进程替换为另一个可执行程序。它的本质是调用了Linux操作系统中的exec系统调用。而exec系统调用是一个家族函数&#xff0c;例如execl、execv、execle、execve等。它们的共同特点是当当前进程执行到该函数时&#xff0c;就会直接…

Bert浅谈

优点 首先&#xff0c;bert的创新点在于利用了双向transformer&#xff0c;这就跟openai的gpt有区别&#xff0c;gpt是采用单向的transformer&#xff0c;而作者认为双向transformer更能够融合上下文的信息。这里双向和单向的区别在于&#xff0c;单向只跟当前位置之前的tocke…

Nginx安装配置与SSL证书安装部署

一、Nginx Nginx是一款高性能的开源Web服务器和反向代理服务器&#xff0c;被广泛用于构建现代化的Web应用和提供静态内容。 nginx官网 这里下载nginx-1.24.0-zip Nginx是一款高性能的开源Web服务器和反向代理服务器&#xff0c;被广泛用于构建现代化的Web应用和提供静态内…

测试开发环境下centos7.9下安装docker的minio

按照以下方法进行 1、安装docker&#xff0c;要是生产等还是要安装docker-ce yum install docker 2、启动docker service docker start 3、 查看docker信息 docker info 4、加到启动里 systemctl enable docker.service 5、开始docker pull minio/minio 但报错&#x…

【机器学习7】优化算法

1 有监督学习的损失函数 1.1 分类问题 对二分类问题&#xff0c; Y{1,−1}&#xff0c; 我们希望sign f(xi,θ)yi&#xff0c; 最自然的损失函数是0-1损失&#xff0c; 函数定义特点0-1损失函数非凸、非光滑&#xff0c;很难直接对该函数进行优化Hinge损失函数当fy≥1时&…

汽车以太网IOP测试新利器

IOP测试目的 汽车以太网物理层IOP&#xff08;Interoperability &#xff09;测试&#xff0c;即测试被测对象以太网物理层之间的互操作性。用于验证车载以太网PHY能否在有限时间内建立稳定的链路&#xff1b;此外&#xff0c;还用于验证车载以太网PHY可靠性相关的诊断特性&am…

Linux环境下C++ 接入OpenSSL

接上一篇&#xff1a;Windows环境下C 安装OpenSSL库 源码编译及使用&#xff08;VS2019&#xff09;_vs2019安装openssl_肥宝Fable的博客-CSDN博客 解决完本地windows环境&#xff0c;想赶紧在外网环境看看是否也正常。毕竟现在只是HelloWorld级别的&#xff0c;等东西多了&am…

浅谈智能安全配电装置应用在银行配电系统中

【摘要】银行是国家重点安全保护部分&#xff0c;关系到社会资金的稳定&#xff0c;也是消防重点单位。消防安全是银行工作的重要组成部分。在银行配电系统中应用智能安全配电装置&#xff0c;可以提高银行的智能控制水平&#xff0c;有效预防电气火灾。 【关键词】银行&#…

如何快速下载mysql的不同版本并启动mysql服务?

如何快速下载mysql的不同版本并启动mysql服务&#xff1f; 下载mysql的安装版本 首先我们要使用到迅雷去下载&#xff0c;因为迅雷下载是很快的。在迅雷里面搜索下面的Mysql Installer安装窗口&#xff0c;如下图&#xff1a; 连接&#xff1a;https://dev.mysql.com/downlo…

fopen/fwrite/fread 对UNICODE字符写入的总结

windows对fopen函数进行了升级&#xff0c;可以支持指定文件的编码格式&#xff08;ccs参数指定&#xff09;。 例如&#xff1a; FILE *fp fopen("newfile.txt", "rt, ccsUTF-8"); 当以 ccs 模式打开文件时&#xff0c;进行读写操作的数据应为 UTF-16…

Selenium自动化测试框架

一.Selenium概述 1.1 什么是框架? 框架&#xff08;framework&#xff09;是一个框子——指其约束性&#xff0c;也是一个架子——指其支撑性。是一个基本概念上的 结构用于去解决或者处理复杂的问题。 框架是整个或部分系统的可重用设计&#xff0c;表现为一组抽象构件及…

【Machine Learning in R - Next Generation • mlr3】

本篇主要介绍mlr3包的基本使用。 一个简单的机器学习流程在mlr3中可被分解为以下几个部分&#xff1a; 创建任务 比如回归、分裂、生存分析、降维、密度任务等等挑选学习器&#xff08;算法/模型&#xff09; 比如随机森林、决策树、SVM、KNN等等训练和预测 创建任务 本次示…