如何使用 JUnit、Spring Boot 和 Flyway 进行测试?
How to test with JUnit, Spring Boot and Flyway?
如何使用 Junit 以正确的方式实现 Fylway?
我在我的项目中添加了 flyway,并将 V1__init.sql(例如)放入 main/resources/db/migration。只要我调试我的代码(不经测试就启动它)它就可以工作。
我是否也必须将 *.sql 文件复制到 test/resources/db/migration 中?
我还希望针对另一个数据库而不是测试数据库进行测试。我是否正确,我必须在测试文件夹下添加另一个 application.properties,我在其中放入构建数据库的凭据(测试 运行 反对?)。
如果有人能帮助我了解如何以正确的方式配置它,我将非常高兴。
您可以将迁移文件保留在 src 下,而无需将它们复制到您的测试文件夹中。当 运行 宁 @SpringBootTest
时,它们已不再使用。这也确保您使用所有 production
迁移进行我们的测试
此外,您不一定需要单独的属性文件进行测试。但你可以。
以下是使用 TestContainers
的 IntegrationTesting 的示例,它使用 application.properties
以及飞路迁移,因为测试的行为就像您通常 运行 应用程序一样。
这是一个抽象 class,它确保测试在整个 Spring 上下文中 运行ning,因此也涉及 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()
);
}
}
}
现在您可以像下面这样定义几个测试 classes:
class MyIntegrationTest extends AbstractPostgreSQLTestContainerIT { }
当 运行在此 class 中执行测试时,Spring引导应用程序启动并使用 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>
如何使用 Junit 以正确的方式实现 Fylway?
我在我的项目中添加了 flyway,并将 V1__init.sql(例如)放入 main/resources/db/migration。只要我调试我的代码(不经测试就启动它)它就可以工作。
我是否也必须将 *.sql 文件复制到 test/resources/db/migration 中?
我还希望针对另一个数据库而不是测试数据库进行测试。我是否正确,我必须在测试文件夹下添加另一个 application.properties,我在其中放入构建数据库的凭据(测试 运行 反对?)。
如果有人能帮助我了解如何以正确的方式配置它,我将非常高兴。
您可以将迁移文件保留在 src 下,而无需将它们复制到您的测试文件夹中。当 运行 宁 @SpringBootTest
时,它们已不再使用。这也确保您使用所有 production
迁移进行我们的测试
此外,您不一定需要单独的属性文件进行测试。但你可以。
以下是使用 TestContainers
的 IntegrationTesting 的示例,它使用 application.properties
以及飞路迁移,因为测试的行为就像您通常 运行 应用程序一样。
这是一个抽象 class,它确保测试在整个 Spring 上下文中 运行ning,因此也涉及 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()
);
}
}
}
现在您可以像下面这样定义几个测试 classes:
class MyIntegrationTest extends AbstractPostgreSQLTestContainerIT { }
当 运行在此 class 中执行测试时,Spring引导应用程序启动并使用 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>