如果没有使用类似flyway的数据库迁移版本控制,而单单使用h2的话,需要每次都导出最新的数据库schema才可以进行靠谱的测试,所以我选择了使用flyway来记录sql版本,这样程序每次跑测试都能将数据库引导最新的数据库版本。
先总结一下h2+flyway构建单元测试的优点:
使用flyway+h2进行单元测试,可以保证随着时间和版本的演进,每次执行测试 时,在h2内存数据库中都会先构建最新的数据库版本,进而保证测试质量。
可以对sql脚本进行即修即测,即改动了sql文件,执行测试可以立即发现诸如sql语法问题,数据库字段和java实体类映射问题等低级问题,极大提高程序员生产效率。
使用H2内存数据库,可以剔除单元测试的数据库环境依赖。
flyway
想到要管理数据库的版本,是在实际产品中遇到问题后想到的一种解决方案,当时各个环境的数据库乱作一团,没有任何一个人(开发、测试、维护人员)能够讲清楚当前环境下的数据库是哪个版本,与哪个版本的应用相匹配,如何升级到与新版本的应用相匹配。
想到管理数据库版本时,先是心底形成了一个初步的解决方案,大致是通过数据库中的某张表来记录数据库表结构的历次更新与对应版本,在每次数据库表结构调整时除了提供库表更新sql ,还必须提供更新记录与对应版本的sql ,以帮助维护数据库版本信息,并在遇到问题时提供相关的排查依据。
相关介绍
引入maven依赖
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
SpringBoot配置
# 指定flyway脚本位置
spring.flyway.locations=classpath:/db/migration
# 打开flyway执行日志
logging.level.org.flywaydb=debug
创建一个migration sql脚本,创建一个表。当然,一个脚本可以创建一张表,也可以删除一张表,也可以创建一个索引,随便你干啥都行,不过脚本一旦在某个环境执行,就不可再修改脚本,否则会报错,因为flyway会对每个执行过的脚本进行哈希校验。flyway会保证每个脚本只在一个具体的环境被执行一次。
image.png
此时启动程序,会看到执行sql脚本的程序日志,若此时连接的是mysql,则在mysql中会看到相关的表被创建了。
2019-05-17 23:00:34.379 [main] DEBUG o.f.c.internal.sqlscript.DefaultSqlScriptExecutor -
Executing SQL: CREATE TABLE "PUBLIC"."flyway_schema_history" (
"installed_rank" INT NOT NULL,
"version" VARCHAR(50),
"description" VARCHAR(200) NOT NULL,
"type" VARCHAR(20) NOT NULL,
"script" VARCHAR(1000) NOT NULL,
"checksum" INT,
"installed_by" VARCHAR(100) NOT NULL,
"installed_on" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
"execution_time" INT NOT NULL,
"success" BOOLEAN NOT NULL
)
2019-05-17 23:00:34.391 [main] DEBUG o.f.c.internal.sqlscript.DefaultSqlScriptExecutor -
Update Count: 0
2019-05-17 23:00:34.391 [main] DEBUG o.f.c.internal.sqlscript.DefaultSqlScriptExecutor -
Executing SQL: ALTER TABLE "PUBLIC"."flyway_schema_history" ADD CONSTRAINT "flyway_schema_history_pk" PRIMARY KEY ("installed_rank")
2019-05-17 23:00:34.404 [main] DEBUG o.f.c.internal.sqlscript.DefaultSqlScriptExecutor -
Update Count: 0
表被创建了
flyway会在数据库中创建 flyway_schema_history表用来记录数据库版本执行信息,从而保证flyawy脚本只能被执行一次。
flyway_schema_history
h2
h2是一款内存数据库,可以在程序执行的时候进行初始化,程序执行过程中增删改查,执行完毕退出自动清除所有内容,可以作为单元测试。
引入maven依赖
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
为了只在测试单元使用h2,我们需要在/test/resource目录下建立相应的properties配置文件,这样执行测试的时候会加载/test/resources目录下的配置文件,而不是/main/resources目录下的配置。
image.png
在测试配置文件中指定h2连接信息
# 这里要用MODE指定模拟的是mysql数据库,否则有些sql会报错
spring.datasource.url=jdbc:h2:mem:h2test;DB_CLOSE_DELAY=-1;MODE=MySQL
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=sa
spring.h2.console.enabled=true
在测试类上指定加载的配置文件
image.png
配置好mybatis和相关mapper,最后执行测试代码
image.png
如此,使用flyway+h2进行单元测试,可以保证随着时间和版本的演进,每次执行测试时,在h2内存数据库中都会先构建最新的数据库版本,进而保证测试质量。而且还有一点,可以对sql脚本进行即修即测,即改动了sql文件,执行测试可以立即发现诸如sql语法问题,数据库字段和java实体类映射问题等低级问题,极大提高程序员生产效率。
网友评论