【问题标题】:How to test with JUnit, Spring Boot and Flyway?如何使用 JUnit、Spring Boot 和 Flyway 进行测试?
【发布时间】:2023-03-26 06:18:02
【问题描述】:

如何使用 Junit 以正确的方式实现 Fylway?

我在我的项目中添加了 flyway 并将 V1__init.sql(例如)放入 ma​​in/resources/db/migration。只要我调试我的代码(在没有测试的情况下启动它)它就可以工作。

我是否也必须将 *.sql 文件复制到 test/resources/db/migration 中?

我还希望针对另一个数据库而不是测试数据库进行测试。我是否正确,我必须在 testfolder 下添加另一个 application.properties,我在其中放置了 buil-database 的凭据(测试运行在哪里?)。

如果有人能帮助我了解如何正确配置它,我会非常高兴。

【问题讨论】:

  • 您可以使用 src 文件夹下的迁移。它们将在运行@SpringBootTest 时使用。因此无需复制它们。此外,您可以使用 TestContainers 对真实数据库实施集成测试,该数据库将中继默认的 application.properties
  • 我阅读了有关测试容器的信息,但我没有为 mysql(仅 postgres)找到它们,我可能想再看看,谢谢。我什至认为,它会从主文件夹中获取 *.sql 文件,但实际上我得到了一个错误,它找不到迁移文件。我会更新我的问题,放置它们可能有错误吗?

标签: junit flyway


【解决方案1】:

您可以将迁移文件保留在 src 下,而无需将它们复制到您的测试文件夹中。运行@SpringBootTest 时,它们已不再使用。这也确保您使用所有 production 迁移进行我们的测试

此外,您不一定需要单独的属性文件进行测试。但你可以。

以下是使用 TestContainers 的 IntegrationTesting 示例,它使用 application.properties 以及 flyway 迁移,因为测试的行为就像您通常运行应用程序一样。

这是一个抽象类,它确保测试在整个 Spring 上下文中运行,因此Flyway 也参与其中。在初始化程序中,数据源配置属性被TestContainers 数据库中的属性覆盖。这样做你直接使用真实的application.properties 并模拟一点真实的;))

@ActiveProfiles("test")
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@ContextConfiguration(initializers = AbstractPostgreSQLTestContainerIT.Initializer.class)
@Testcontainers
public abstract class AbstractPostgreSQLTestContainerIT {
    private static final String POSTGRES_VERSION = "postgres:11.1";
    public static PostgreSQLContainer database;

    static {
        database = new PostgreSQLContainer(POSTGRES_VERSION);
        database.start();
    }

    static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
        @Override
        public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
            TestPropertySourceUtils.addInlinedPropertiesToEnvironment(
                    configurableApplicationContext,
                    "spring.datasource.url=" + database.getJdbcUrl(),
                    "spring.datasource.username=" + database.getUsername(),
                    "spring.datasource.password=" + database.getPassword()
            );
        }
    }
}

现在您可以定义几个测试类,如下所示:

class MyIntegrationTest extends AbstractPostgreSQLTestContainerIT { }

在此类中运行测试时,SpringBoot 应用程序启动并使用TestContainers 数据库。

出于我的目的,我还实现了一个简单的注释:

@TransactionalSQLTest("classpath:db/test/create_base_foo_data.sql")
void updateFooByExternalIdentifier_DTOProvided_ShouldReturnUpdatedFoo() {}

代码

/**
 * Annotation which allows to provide SQL Scripts for a certain IT test.
 * The transactional ensures that data is cleaned up after test.
 */
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Transactional
@Test
@Sql
public @interface TransactionalSQLTest {
    @AliasFor(attribute = "value", annotation = Sql.class)
    String[] value() default {};

    @AliasFor(attribute = "executionPhase", annotation = Sql.class)
    Sql.ExecutionPhase executionPhase() default Sql.ExecutionPhase.BEFORE_TEST_METHOD;
}

使用注释,您可以为 SQL 提供例如用于测试的样本数据。

pom.xml

<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>testcontainers</artifactId>
    <version>${testcontainers.version}</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>postgresql</artifactId>
    <version>${testcontainers.version}</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>${testcontainers.version}</version>
    <scope>test</scope>
</dependency>

这应该是MySql的依赖

<!-- https://mvnrepository.com/artifact/org.testcontainers/mysql -->
<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>mysql</artifactId>
    <version>1.15.3</version>
    <scope>test</scope>
</dependency>

【讨论】:

  • 非常感谢!太好了,我像下面的代码一样使用 MySqlContainer 对其进行了测试,但是我收到错误消息“您没有超级权限并且启用了二进制日志记录”。你知道这可能是什么问题吗? Docker 看起来很棒,我可能会花一些时间来了解更多。
  • 你在Linux下运行吗?如果我没记错的话,那么您正在运行 IDE 的用户需要添加到特定组中。否则 docker 容器不会启动。进一步:你安装了 docker 吗?如果不是:TestContainers 基于 docker,因此必须安装它
  • 我正在使用 MacOs 并且我安装了 Docker。当我创建数据库时,如 database = new MySQLContainer();它可以工作,但是不推荐使用此构造函数。我是否理解正确,docker mysql 实例仅用于测试?在开发例如新视图时,我应该使用我的本地数据库(所以与测试使用的不同?)
  • 当然。您应该只将 TeatContainers 用于测试目的,因为在您的测试之后数据库会被解构。但是您可以将 Docker 用于本地数据库。
  • 您可以配置初始数据,例如sql 文件到静态初始化程序中的 TestContainer。应该有对应的mutator方法
猜你喜欢
  • 2019-02-02
  • 2018-05-25
  • 2021-01-24
  • 2019-02-19
  • 2020-05-28
  • 2018-10-07
  • 2019-05-10
  • 2017-04-22
  • 2018-11-09
相关资源
最近更新 更多