【问题标题】:SpringbootTest + TestContainers: how do I refresh the database after tests pollute the databaseSpringbootTest + TestContainers:测试污染数据库后如何刷新数据库
【发布时间】:2019-10-15 11:36:12
【问题描述】:

我正在使用这样的抽象类:

@SpringBootTest(classes = MyAppApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT)
@ActiveProfiles("test")
public abstract class AbstractIntegrationTest {

    static {
        PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer().withPassword("password")
                .withUsername("postgres").withDatabaseName("MyApp");
        postgreSQLContainer.start();

        System.setProperty("spring.datasource.url", postgreSQLContainer.getJdbcUrl());
        System.setProperty("spring.datasource.password", postgreSQLContainer.getPassword());
        System.setProperty("spring.datasource.username", postgreSQLContainer.getUsername());

    }

然后我有很多测试利用了这样的类:

public class moreTests extends AbstractIntegrationTest {

    TestRestTemplate restTemplate = new TestRestTemplate("my-user", "password"); 
    HttpHeaders headers = new HttpHeaders();

    @Test
    public void SimpleHealthCheck() {    
        HttpEntity<String> entity = new HttpEntity<String>(null, headers);    
        ResponseEntity<String> response = restTemplate.exchange(
                createURLWithPort("/api/v1/healthcheck"),
                HttpMethod.GET, entity, String.class);    
        assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));
    }

    @Test
    public void GetInst() {    
        HttpEntity<String> entity = new HttpEntity<String>(null, headers);    
        ResponseEntity<String> response = restTemplate.exchange(
                createURLWithPort("/api/v1/institutions"),
                HttpMethod.GET, entity, String.class);
        assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));    
    }

但是,我的一些测试会污染数据库。我想控制测试是否使用新数据库运行。执行此操作的规定方法是什么?

【问题讨论】:

    标签: postgresql spring-boot spring-boot-test testcontainers


    【解决方案1】:

    在阅读了有关 Spring Boot 集成测试的更多信息后,似乎规定的方法是对破坏性(或脏)的测试使用“@DirtiesContext”注释。

    编辑:几个月后,我意识到@DirtiesContext 并不好。它基本上重置了整个应用程序,这可能很昂贵。此外,@DirtiesContext 在某些情况下可能不会重置您的数据库,具体取决于您的应用程序的工作方式。我建议在每个测试类的 @BeforeAll 或 @AfterAll 部分中运行一个清理 SQL 脚本。这个清理 SQL 脚本需要仔细编写。

    【讨论】:

    • AbstractIntegrationTest 在静态初始化块中运行 Postgres,这个数据库实例对于您的所有测试套件都是单一的,使用 DirtiesContext 在删除 spring 上下文后不会给您一个干净的数据库在缓存中。在这种情况下,你需要做一些自我准备来清理postgres中的错误数据。
    • 好点。使用我们的 Spring Boot 应用程序,在启动过程中,有一个脚本可以在启动过程中清理数据库......所以是的,这可能不适用于所有人。其他人可能希望在破坏性测试后使用如下注释清理他们的数据库:@Sql(scripts={"classpath:CleanUpDatabase.sql"})
    【解决方案2】:

    您可以使用 @Before 注释在执行测试之前清理所有内容。

    或者你在执行之前清理每个测试。

    每个测试都应该相互独立。所以通常:

    • 明确并设定期望
    • 运行测试

    如果测试失败,您的数据库将处于失败状态,以便您检查发生了什么。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-14
      • 2017-11-03
      • 2022-10-25
      • 2014-10-15
      • 2013-02-14
      • 1970-01-01
      • 2016-07-25
      • 1970-01-01
      相关资源
      最近更新 更多