如何使用JUnit、Sping Boot 和Flyway进行测试?

qjp7pelc  于 2022-11-11  发布在  其他
关注(0)|答案(1)|浏览(225)

我如何用Junit以正确的方式实现Flyway?
我将Flyway添加到我的项目中,并将V1__init.sql(例如)放入**main**/resources/db/migration目录中。只要我调试代码(启动时不进行测试),它就可以工作。
我是否也必须将*.sql文件复制到**test**/resources/db/migration目录中?
我还希望,测试是针对另一个数据库而不是测试数据库进行的。我是否正确,我必须在test文件夹下添加另一个application.properties文件,我在其中放置了构建数据库的凭据(测试运行的位置?)。
如果有人能帮助我了解如何正确配置它,我会非常高兴。

u1ehiz5o

u1ehiz5o1#

您可以将迁移文件保留在src下,而不需要将它们复制到您的test文件夹中。它们将在运行@SpringBootTest时使用。
此外,您不一定需要一个单独的属性文件来进行测试,但您可以有一个。
以下是使用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>

相关问题