SpringBoot单元测试神器Testcontainers

哈骞仕
2023-12-01

一、背景

SpringBoot进行单元测试的时候,基本上都离不开MySQL,而单元测试应该是不依赖于任何环境的,所以最初我们采用的单元测试的方法是mock组件的方式。如今随着docker技术越来越成熟,现在用在单元测试方面也变得更加方便。

  1. Testcontainers
    Testcontainers是github开源组件,是利用本地启动docker容器的方式来替代环境中的组件,目前支持的组件有,mysql,redis,clickhouse,oralce,kafka,db2,minio等一系列组件。而用户只需要启动springboot工程所依赖的组件,单元测试连接容器化组件,即可不依赖环境。

  2. Testcontainers-spring-boot
    Testcontainers-spring-boot是在Testcontainers的基础上简化了用户创建容器化的方式,只需要引入依赖,再通过配置的方式即可快速创建容器,并注入到SpringBoot上下文对象中。使用简单,方便,高效。
    详见Github: https://github.com/Playtika/testcontainers-spring-boot

二、使用方式


本地运行环境先自行安装docker


  1. 引入依赖
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <version>2.3.5.RELEASE</version>
      <scope>test</scope>
    </dependency>
    
	<dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-bootstrap</artifactId>
      <version>3.0.5</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>com.playtika.testcontainers</groupId>
      <artifactId>embedded-mysql</artifactId>
      <version>2.2.0</version>
      <scope>test</scope>
    </dependency>

按需求添加其他容器组件,如redis,kafka,clickhouse等

  1. 添加配置(以下配置添加到test资源下的resources中)
  • test resource中添加application.properties文件
#忽略spring boot和spring clould版本校验冲突
spring.cloud.compatibility-verifier.enabled=false
#用docker容器的mysql配置覆盖spring启动类的mysql属性
spring.datasource.mysql.host=${embedded.mysql.host}
spring.datasource.mysql.port=${embedded.mysql.port}
spring.datasource.mysql.database=${embedded.mysql.schema}
spring.datasource.mysql.username=${embedded.mysql.user}
spring.datasource.mysql.password=${embedded.mysql.password}

一定要根据自己spring的mysql配置属性进行注入

  • test resources中添加bootstrap.properties文件
#启用容器
embedded.containers.enabled=true
#可以指定mysql的image版本,默认8.0
embedded.mysql.dockerImage=mysql:5.7
#数据库初始化的建表语句
embedded.mysql.initScriptPath=mysql_init.sql

三、Test

以下测试过程会自动创建mysql容器,并连接到创建的容器中,测试完成后自动销毁容器

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserServiceTest {

	@Resource
    private UserService userService;

    @Test
    public void test() throws InterruptedException {
        //userService.create()为本工程insert mysql用户表的操作
        Long id = userService.create(CreateUserRequest
                .builder()
                .name("测试")
                .phone("18888888888")
                .build());
       //userService.queryById()为本工程查询 mysql用户表的操作
        UserResponse response = userService.queryById(id);
        System.out.println(JSONObject.toJSONString(response));
    }
}
 类似资料: