You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 18:43:12