SpringBoot单元测试实践——数据隔离篇(TestContainers)

2023年 8月 18日 16.0k 0

前言

在上篇文章《SpringBoot单元测试实践——数据隔离篇》中,我们讨论了如何进行数据隔离,但是无论哪种方式,都无法做到完全的数据隔离,因为我们始终依赖了一个外部的数据库,不管是开发环境亦或是测试环境,而对于外部的数据源,我们是无法进行管控的,我们无法保证有谁会对我们依赖的数据库做什么操作,因此无法保证我们单元测试的准确性。因此,神器TestContainers立功的时候到了,它是一个Java的三方库,它的功能很简单,就是可以在我们运行单元测试时,临时帮我们拉起一个Doker镜像,比如我临时拉一个MySQL镜像起来,那它就是一个完全独立的数据库,只用于本次测试,测试结束后又会自动销毁。

依赖配置

首先它的功能是拉起一个Doker镜像,那我们的单元测试环境中必须要安装了Docker,这是前提。然后需要配置我们的maven依赖:



        
            org.testcontainers
            testcontainers
            1.18.3
            test
        

        
            org.testcontainers
            mysql
            1.18.3
            test
        

        
            org.testcontainers
            junit-jupiter
            1.18.3
            test
        

测试代码

配置完依赖之后,就可以开始写我们的单元测试代码了:

@Testcontainers
@SpringBootTest
public class ContainersTest {
    
    /**
     * 通过@Container注解标记这是一个container
     */
    @Container
    public MySQLContainer mysqlContainer = new MySQLContainer(DockerImageName.parse("mysql:8.0-debian")).withExposedPorts(3306);

    /**
     * 覆盖数据库配置
     */
    @DynamicPropertySource
    public void dynamicProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.datasource.url", () -> mysqlContainer.getJdbcUrl());
        registry.add("spring.datasource.driverClassName", () -> mysqlContainer.getDriverClassName());
        registry.add("spring.datasource.username", () -> mysqlContainer.getUsername());
        registry.add("spring.datasource.password", () -> mysqlContainer.getPassword());
    }

    /**
     * 测试用例
     */
    @Sql(
            scripts = "create-data.sql",
            config = @SqlConfig(transactionMode = ISOLATED)
    )
    @Test
    public void testSaveOrUpdate() {
        //do something db operation
    }

}
  • @Testcontainers是一个Junit Jupiter的扩展,它会在测试运行前后自动启动和关闭我们的容器,即下面的@Container注解标记的容器。
  • 然后我们通过MySQLContainer定义了一个MySQL容器,创建方式是通过Docker镜像,版本是mysql:8.0-debian,这个容器会在测试运行前启动。
  • 下面通过@DynamicPropertySource来覆盖了原来的配置,这个在之前的《SpringBoot单元测试实践——配置隔离篇》。中有讲到过。
  • @Sql注解用于测试前来执行一段SQL脚本,用于初始化数据库。
  • 经过这些配置之后,那我们每次运行单元测试,它都会拉起一个MySQL镜像,然后我们获取它的数据信息,替换掉原来的配置,并且初始化数据。就可以保证每次运行单元测试,都有一个干净的环境,并且不会受到其它外部因素的影响。

    总结

    上面介绍了如何使用TestContainers来自动运行Docker镜像,从而保证数据的隔离,而且不仅仅是数据库,其它的包括Redis、Kafka等中间件,都可以通过这种方式进行隔离,这样就可以保证我们的单元测试完全是独立运行的,可以保证它的稳定性正确性。但是它不是所有的场景都适用,首先需要有Docker环境,其次拉起很多镜像的话,会对内存有要求,而且单元测试的运行时间也会变得更长。大家可以根据自己的实际情况来选择合适的数据隔离方案。

    相关文章

    JavaScript2024新功能:Object.groupBy、正则表达式v标志
    PHP trim 函数对多字节字符的使用和限制
    新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
    使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
    为React 19做准备:WordPress 6.6用户指南
    如何删除WordPress中的所有评论

    发布评论