有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Spring boot和Flyway:在集成测试之前清除数据库数据

我正在使用Spring boot framework(v2.0.2)构建一个REST服务,在那里我在数据库上运行集成测试。我在谷歌上搜索了很多关于测试前清理数据库的文章,但不幸的是,我发现它们要么效率低下,要么是黑客攻击,不适合Spring boot。你能不能容忍我,提出解决这个问题的好办法

理想情况下,我认为数据库不应该在每次测试之前清除,而应该在某组测试之前清除,比如套件或者每个测试类。其中一个建议如下所示:

@Autowired
protected Flyway flyway;

@Before
public void init() {
    flyway.clean();
    flyway.migrate();
}

它在每次测试前重建数据库,显然效率不高。将其更改为静态上下文并使用@BeforeClass不起作用,因为Spring不会注入静态字段

有没有什么好方法可以从静态环境中访问这个flyway bean,从而使这个解决方案有效

这里的子问题:Flyway有一个clean命令,它不仅清除数据,而且删除所有内容,然后migrate命令再次执行迁移。这看起来也像是开销。由于迁移是在启动时检查的,所以我认为没有必要在每个测试组之前拆除并重建所有内容。仅仅清理数据就足够了。你能就如何实现这一目标给出一些建议吗

总之,我正在寻找一种标准的方法,在每组集成测试(例如,每个类)之前删除数据库数据(如果可能的话,不是表)。我想每个人在使用Spring boot时都会面临这个任务,所以在框架本身中可能会考虑一些不错的解决方案

谢谢你


共 (1) 个答案

  1. # 1 楼答案

    这个答案很有用,但它并没有让我一路走到那里,所以我想我会回来补充一个答案,以防其他人想解决同样的问题。上面的bean定义非常棒

    有5种左右可能性的弹簧外形。我查看了文档以及人们如何使用它们,但走了另一条路。Maven有6个作用域,但在本例中有用的是runtime和test

    当我深入研究spring概要以及人们可以在它们之间切换的各种方式时,我的情况似乎有点太复杂了。我只希望我的测试数据库被创建、检查并填充一些数据,这样我就可以在我的jpa spring boot应用程序中测试存储库。我不想花4个小时建立个人资料。并不是说从长远来看这不是一个值得的努力,只是我想让事情进展起来

    当我执行spring boot:run时,我希望迁移非测试数据库,但不希望其中有任何用于测试的crud数据

    因此,在live app中,我希望有一个几乎为空的数据库,在测试期间,我希望flyway清理数据库,运行版本化迁移,并用测试数据填充数据库

    上面的答案让我找到了一个解决方案,随着我的项目越来越接近生产,我可能会将其纳入spring概要文件中

    事实证明,spring boot test提供了一个@TestConfiguration注释,您可以将它附加到src/test/hierarchy中的任何类。我创建了一个FlywayConfiguration类,其中包含上面提供的bean定义:

    package com.foo.fooservice;
    
    import org.flywaydb.core.Flyway;
    import org.springframework.boot.autoconfigure.flyway.FlywayMigrationStrategy;
    import org.springframework.boot.test.context.TestConfiguration;
    import org.springframework.context.annotation.Bean;
    
    @TestConfiguration
    public class FlywayMigrationConfig {
    
    @Bean
    public static FlywayMigrationStrategy cleanMigrateStrategy(){
    
            return flyway -> {
                    flyway.clean();
                    flyway.migrate();
                    };
            }
    }
    

    现在,如果我想在测试中使用它,我在适当的测试类中添加了另一个漂亮的注释@Includes,它是@TestConfiguration注释的一个伴侣,这样我就可以像使用@BeforeClass一样使用这个配置了:

    @DataJpaTest
    @Import(FlywayMigrationConfig.class) 
    @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
    class AccountUserRepoTest {
    
    
    
        @Autowired 
        private AccountUserRepo accountUserRepo;
    
        @Autowired
        private FlywayMigrationStrategy strategy;
    

    这使我能够在每个测试类的基础上注入这种flyway迁移策略。Spring不会自动将bean注入到每个测试类中,现在只需将@Includes注释添加到适当的测试类中,就可以使用这个配置。您不必在每个要使用bean的测试类中定义它。只需使用@Includes(your@TestCongiguration-注释类)

    我碰巧使用的是postgresSQL,而不是H2,因为我认为如果我在存储库实体上进行集成测试,我可能会根据我将在生产中使用的内容进行测试

    另外:src/main/resources将jdbc和flyway属性设置为dev模式名和jdbc url

    src/test/resources/application。属性将架构名称设置为“test”(可以随意命名)

    这种方法的一个缺点是粒度,您可能不希望这样做——对于以这种方式配置的每个测试类,都会清理并重新填充数据库

    我个人喜欢这样,因为对于我正在测试的每个存储库类,我都希望数据被刷新。如果我正在处理一个特定的测试类,我也喜欢这样,在这个粒度级别上进行配置意味着“运行测试”是开箱即用的。IDE中不需要特殊配置就可以工作