当前位置: 首页 > 知识库问答 >
问题:

Spring@SQL注释,是否可以在所有测试之前运行一次?

田谦
2023-03-14

使用Spring进行集成测试,我可以填充一个运行脚本的测试数据库,如下所示...

@Test
@Sql({"/db/schema.sql", "/db/accountConfig.sql", "/db/functions/fnSomething.sql"})
public void verifySomething() {
   ...
}

我使用的是JUnit4、Spring Boot、Java15、TestContainers。

我试过的事情...

  • 我曾尝试在我的测试类扩展的类上使用@beforeClass,但它似乎在我的测试之后运行。
  • TestContainers确实有一个init脚本函数,但它只接受一个文件,这并不理想。
  • 我也尝试过scriptutils.executesqlscript,但是出于某种原因,测试容器不喜欢这样。

下面是我的示例代码,它可以与@sql一起工作,但不能与scriptutils.executesQLScript一起工作。

@ContextConfiguration(initializers = AbstractIntegrationTest.Initializer.class)
public abstract class AbstractIntegrationTest {

    @ClassRule 
    public static MSSQLServerContainer mssqlserver = new MSSQLServerContainer();

  
    public static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {

        @Override
        public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
            ConfigurableEnvironment environment = configurableApplicationContext.getEnvironment();
            Properties props = new Properties();
            props.put("spring.datasource.driver-class-name", mssqlserver.getDriverClassName());
            props.put("spring.datasource.url", mssqlserver.getJdbcUrl());
            props.put("spring.datasource.username", mssqlserver.getUsername());
            props.put("spring.datasource.password", mssqlserver.getPassword());

            environment
                .getPropertySources()
                .addFirst(new PropertiesPropertySource("myTestDBProps", props));      

            configurableApplicationContext.setEnvironment(environment);
    }
}

我的测试类只是扩展AbstractIntegrationTest。但是使用@sql可以为每个测试用例运行脚本。有人对初始化SQL脚本的更好方法有什么建议吗?尝试了flyway,但它不允许从脚本创建DB。

共有1个答案

桂志新
2023-03-14

我建议查看一下在Spring上下文初始化时执行一次SQL脚本的数据库初始化器bean。基本上,根据您使用JDBC还是R2DBC,有两种解决方案。由于要初始化多个脚本,因此应该使用CompositeDatabasePopulator。还要记住导入正确的类,因为它们具有相同的名称,但来自不同的包,这同样取决于jdbc/r2dbc。

要从resources文件夹加载资源,可以使用以下任一选项:

  • resource resource=new ClassPathResource(“sql/schema.sql”))
  • @value(“classpath:sql/schema.sql”)资源资源

这个解决方案相当灵活,因为您可以使用@testconfiguration为测试上下文定义初始化器bean(请记住,使用这个注释有点棘手,所以我请您参阅这篇文章:Spring的@testconfiguration的怪癖对我帮助很大)。

该解决方案应该适用于任何具有ConnectionFactory可用的解决方案,包括测试容器。

  • 使用org.springframework.jdbc.datasource.init.CompositeDatabasePopulator
  • 使用org.springframework.jdbc.datasource.init.resourceDatabasePopulator

通过调用populate进行的初始化必须在@PostConstuct中进行,因为Spring Boot不会自动检测到populator。我建议将以下代码段包装在配置类中,并将其包含到测试范围中。

@Autowired
private DataSource dataSource;

@PostConstruct
public void initData() throws SQLException {

    var populator = new CompositeDatabasePopulator();
    populator.addPopulators(new ResourceDatabasePopulator(new ClassPathResource("sql/schema.sql")));
    populator.addPopulators(new ResourceDatabasePopulator(new ClassPathResource("sql/catalog.sql")));
    populator.addPopulators(new ResourceDatabasePopulator(new ClassPathResource("sql/data.sql")));

    populator.populate(dataSource.getConnection());
}
  • 使用org.springframework.r2dbc.connection.init.CompositeDatabasePopulator
  • 使用org.springframework.r2dbc.connection.init.resourceDatabasePopulator

您可以使用ConnectionFactoryInitializer,它在加载Spring上下文时初始化添加到该初始化器中的所有填充器一次。

@Bean
public ConnectionFactoryInitializer initializer(ConnectionFactory connectionFactory) {

    var populator = new CompositeDatabasePopulator();
    populator.addPopulators(new ResourceDatabasePopulator(new ClassPathResource("sql/schema.sql")));
    populator.addPopulators(new ResourceDatabasePopulator(new ClassPathResource("sql/catalog.sql")));
    populator.addPopulators(new ResourceDatabasePopulator(new ClassPathResource("sql/data.sql")));


    var initializer = new ConnectionFactoryInitializer();
    initializer.setConnectionFactory(connectionFactory);
    initializer.setDatabasePopulator(populator);

    return initializer;
}
 类似资料:
  • 我是新来的春靴AOP。 用@Before注释的AOP方法是否在java验证注释(例如@NotNull)之前运行? 我还需要为每个请求运行一些其他自定义验证,但我需要在java验证注释运行之后运行这些验证。 哪个先跑? 我的控制器: 我的建议是:

  • 我试图弄清楚是否可以在Express.js应用程序的上下文中运行TestCafe测试。我的想法是创建一个表单,接受输入(如UPC代码),然后单击表单上的submit,它将导致TestCafe测试以无头模式(在某处)生成,并将UPC加载到此页面https://www.ebay.com/sh/research. 从那里,TestCafe将从页面获得结果并将它们粘贴到我的数据库中。 我把测试放在一个名为

  • 问题内容: 如果是跑它运行在您的文件结尾通过运行启动格式的功能和使用(* T testing.T)模块。我想知道文件中的每个功能是同时运行还是确定地分别运行每个功能?是否为每个人创建一个执行例程?如果确实为每个例程创建了一个go例程,是否可以某种方式监视go例程?是否有可能做类似的事情并为每个实例获取一个实例并对其进行监控,诸如此类? 注意:这个问题假设您使用go(测试)随附的测试框架。 问题答案

  • 我想使用Mongock迁移工具来初始化存储在数据库中的应用程序配置。我遇到的问题是我的一个配置在使用@Configuration注释的类中使用。由于Mongock更改集在@Configuration之后执行,它无法从数据库中检索尚未存在的值,这会导致应用程序崩溃。有没有办法推迟创建@Configuration类?或者我应该在不使用mongock的情况下初始化这个配置?

  • 方法和测试位于一个类中,例如 下面是我的testng.xml的示例,其中包含了包含功能测试的包 UPD.post修改后的代码中包含AfterTest。我只使用before/aftermethod注释