写点什么

SpringBoot 中如何对数据访问层进行单元测试?

作者:java易二三
  • 2023-08-24
    湖南
  • 本文字数:1601 字

    阅读完需:约 5 分钟

前言我们公司作为一个面向银行、金融机构的 TO B 类企业,频繁遇到各个甲方爸爸提出的国产化数据库的改造需求,包括 OceanBase, TiDB,geldenDB 等等。每次适配都需要投入大量的人力进行测试工作,那么有没有更高效、低成本的方式去解决这个问题呢?本文就介绍一种快高效、可复用的解决方案——对数据访问层做单元测试。Mybatis 测试依赖我们项目采用的 SpringBoot + Mybatis 作为开发框架,大家第一想到可以用 SpringBoot 自带的测试注解 @SpringBootTest 进行测试。但是使用该注解有一个最大的弊端就是需要启动整个容器,注入全部的 bean,那么一次测试就相当于启动一次应用,我们的应用启动一次就要花费近 70~80 秒,黄花菜都凉了。


那么有没有更好的办法,有必要注入全量的 bean 吗?是不是只要注入数据访问层相关的 bean 即可,其实官方的 mybatis 就给了我们这样的的解决方案。


引入依赖 mybatis-spring-boot-starter-test


xml 复制代码<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter-test</artifactId><version>2.3.0</version><scope>test</scope></dependency>


Mapper 接口


less 复制代码 @Mapperpublic interface CityMapper {


@Select("SELECT * FROM CITY WHERE state = #{state}")City findByState(@Param("state") String state);
复制代码


}


使用 junit5 的测试类


less 复制代码// 使用 junit5@MybatisTest// 使用真实的数据源进行测试 @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)public class CityMapperTest {


@Autowiredprivate CityMapper cityMapper;
@Testpublic void findByStateTest() { City city = cityMapper.findByState("CA"); assertThat(city.getName()).isEqualTo("San Francisco"); assertThat(city.getState()).isEqualTo("CA"); assertThat(city.getCountry()).isEqualTo("US");}
复制代码


}


自定义一个启动类


@MybatisTest 在默认情况下将会探测到带有 @SpringBootApplication 的类。 因此,由于 bean 定义的一些方法,可能会发生一些意想不到的错误,或者一些不必要的组件被装入 ApplicationContext 。 为了避免这种情况,我们可以在与测试类相同的包中创建带有 @SpringBootApplication 的类。java 复制代码 package sample.mybatis.mapper;


import org.springframework.boot.autoconfigure.SpringBootApplication;


@SpringBootApplicationclass MapperTestApplication {


}


运行结果


详细内容参考 github.com/mybatis/spr…但是, 上面是使用原生 mybatis 的测试方式,而我们项目用的是基于 mybatis 封装的开源框架 tkMapper,github 地址是https://github.com/abel533/Mapper,并不适用啊,无解,只能去看下 mybatis-spring-boot-starter-test 的原理。实现原理实际上 mybatis-spring-boot-starter-test 的实现原理很简单,代码目录结构如下:


@MybatisTest 注解如下,引入 MybatisTestContextBootstrapper 测试引导程序。同时引入其他的注解,进行自动装配。


@AutoConfigureMybatis 由 MybatisTest 注解引入,会去找 META-INF 下的 spring.factories,自动组装 mybatis 相关的 bean


那么基于目前的理解,我们也可以简单实现一个基于 TkMapper 的测试框架。Mapper 测试框架我们参照 mybatis 原生的实现方式


重新命名,内容不变


修改 spring.factories 添加 MapperAutoConfiguration


使用自定义测试注解 @MapperTest


虽然这里有 insert 语句,但是测试结束,数据不会真的插入到表中,因为 MapperTest 注解上包含了事务注解,所以是可以反复进行测试的。


总结本文分享了基于 springboot+mybatis 项目中针对数据访问层进行单元测试的一种方式,这种方式只注入 mybatis 相关的 bean,快速高效的对不同类型的数据库进行测试,保证程序的正确性。其实,对于大多数据的程序员来说,写单元测试可能是一种负担和累赘,但是如果你的单元测试真的能够在你的项目中有其价值,那么就是值得的,千万不要为了单元测试而单元测试。

用户头像

java易二三

关注

还未添加个人签名 2021-11-23 加入

还未添加个人简介

评论

发布
暂无评论
SpringBoot中如何对数据访问层进行单元测试?_Java_java易二三_InfoQ写作社区