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

时间:2018-06-18 18:58:52

标签: java spring-boot junit flyway

我正在使用Spring引导框架(v2.0.2)构建REST服务,我在其中运行在数据库上运行的集成测试。我搜索了很多,并且在测试之前有大量关于清理数据库的文章,但不幸的是我发现它们效率低下或黑客攻击而不是Spring引导。请问你能忍受我并为这个问题提出一个好方法吗?

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

@Autowired
protected Flyway flyway;

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

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

是否有一些很好的方法可以从静态上下文中获取此flyway bean,以使此解决方案有效?

这里的子问题: Flyway有一个命令clean,它不仅清除数据,而且删除所有内容,然后migrate命令再次执行迁移。这似乎也是开销。无论如何在启动时检查迁移,我都没有看到在每个测试组之前拆除和重建所有内容的必要性。只需清除数据就足够了。您能就如何实现这一目标提出一些建议吗?

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

谢谢!

2 个答案:

答案 0 :(得分:3)

您可以为测试创建配置文件。它会在所有测试之前运行一次。

startx

答案 1 :(得分:3)

这个答案很有用,但是并不能帮助我一路走下去,所以我想我会回来添加一个答案,以防其他人想解决这个问题。上面的bean定义很棒。

有些弹簧轮廓可能有5种左右的可能性。我看了看文档以及人们如何使用它们,但是又走了另一条路。 Maven有6个作用域,但在这种情况下有用的是运行时和测试。

当我研究弹簧轮廓以及可以在它们之间切换的各种方式时,对我来说情况似乎有点太复杂了。我只希望创建,构造和填充要测试的数据库,并添加一些数据,以便可以在jpa spring boot应用程序中测试存储库。我不想花4个小时来建立个人资料。从长远来看,这并不是一个值得的努力,只是我想让事情前进。

当我执行spring-boot:run时,我希望迁移非测试数据库,但是我不想在其中使用任何用于测试的原始数据。

因此,在实时应用程序中,我需要一个几乎为空的数据库,并且在测试期间,我希望使用flyway清理数据库,运行版本化的迁移并用测试数据填充它。

以上答案使我找到了一个解决方案,随着我的项目越来越接近生产,我可能会把它折叠成弹簧轮廓。

结果证明spring-boot-test提供了一个@TestConfiguration批注,您可以将其附加到src / test /层次结构中的任何类。我创建了一个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;

这使我可以在每个测试类别的基础上注入这种飞行路线迁移策略。 Spring不会将您的bean自动注入每个测试类中,您现在可以通过将@Includes批注添加到适当的测试类中来使用此配置。您不必在每个要使用它的测试类中定义bean。只需使用@Includes(您的@TestCongiguration注释类)即可。

我碰巧使用的是postgresSQL而不是H2,因为我认为如果我正在对存储库实体进行集成测试,那么我也可能会针对生产环境使用它。

此外:src / main / resources将jdbc和flyway属性设置为开发模式名称和jdbc url。

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

您可能不希望的这种方法的一个缺点是粒度-为您以此方式配置的每个测试类清除并重新填充数据库。

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