如何在Spring Configuration中配置SQL脚本以实现测试间共享?
完全可行,提供两种实用实现方案
方案一:容器初始化时执行SQL脚本(全局一次性执行)
通过@PostConstruct结合Spring的ScriptUtils工具类,在配置类中完成SQL脚本的执行。这种方式会在Spring容器初始化完成后立刻执行脚本,所有导入该配置类的测试类共享这一份初始化数据。
实现代码
配置类:
import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import org.springframework.jdbc.datasource.init.ScriptUtils; import javax.annotation.PostConstruct; import javax.sql.DataSource; @Configuration public class TestDataInitConfig { private final DataSource dataSource; public TestDataInitConfig(DataSource dataSource) { this.dataSource = dataSource; } @PostConstruct public void loadTestData() throws Exception { // 执行classpath下的SQL脚本,支持同时指定多个脚本文件 ScriptUtils.executeSqlScript( dataSource.getConnection(), new ClassPathResource("sql/test-init-data.sql"), new ClassPathResource("sql/test-extra-data.sql") ); } }
测试类使用:
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import org.springframework.context.annotation.Import; @SpringJUnitConfig @Import(TestDataInitConfig.class) public class UserServiceTest { // 测试方法执行前,数据已完成插入 }
注意点
- 脚本路径要对应classpath下的实际位置,比如
sql/test-init-data.sql表示放在resources/sql目录下 - 可通过
ScriptUtils的重载方法设置参数,比如ignoreFailedDrops = true忽略删除语句的错误,或者指定SQL分隔符等
方案二:贴合测试生命周期执行脚本(按需执行)
如果需要在每个测试方法执行前重新执行脚本(避免测试间数据污染),可以自定义TestExecutionListener,并在配置类中注册这个监听器。
实现代码
自定义测试监听器:
import org.springframework.test.context.TestContext; import org.springframework.test.context.support.AbstractTestExecutionListener; import org.springframework.core.io.ClassPathResource; import org.springframework.jdbc.datasource.init.ScriptUtils; import javax.sql.DataSource; public class PreTestSqlScriptListener extends AbstractTestExecutionListener { @Override public void beforeTestMethod(TestContext testContext) throws Exception { DataSource dataSource = testContext.getApplicationContext().getBean(DataSource.class); // 每个测试方法执行前执行脚本 ScriptUtils.executeSqlScript( dataSource.getConnection(), new ClassPathResource("sql/test-clean-data.sql"), new ClassPathResource("sql/test-init-data.sql") ); } }
配置类注册监听器:
import org.springframework.context.annotation.Configuration; import org.springframework.test.context.TestExecutionListeners; import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; @Configuration @TestExecutionListeners( listeners = PreTestSqlScriptListener.class, mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS ) public class TestDataExecutionConfig { // 仅用于注册自定义监听器,无需额外代码 }
测试类使用:
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import org.springframework.context.annotation.Import; @SpringJUnitConfig @Import(TestDataExecutionConfig.class) public class OrderServiceTest { // 每个测试方法执行前都会重新执行脚本,保证数据干净 }
注意点
mergeMode = MERGE_WITH_DEFAULTS必须设置,否则会覆盖Spring Test默认的监听器(比如负责依赖注入的监听器),导致测试类无法正常注入Bean- 如果需要在整个测试类执行前只执行一次脚本,可重写
beforeTestClass方法替代beforeTestMethod
内容的提问来源于stack exchange,提问作者user1589188
相关产品推荐
相关产品推荐

