SpringbootTest + TestContainers: как обновить базу данных после того, как тесты загрязняют базу данных

Я использую такой абстрактный класс:

@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));    
    }

Однако некоторые из моих тестов загрязняют базу данных. Я хотел бы контролировать, запускается ли тест со свежей базой данных или нет. Как это сделать предписанным способом?


person user952342    schedule 29.05.2019    source источник


Ответы (2)


После дополнительного чтения о тестировании интеграции загрузки Spring выяснилось, что предписанный способ - использовать аннотацию @DirtiesContext для тестов, которые являются деструктивными (или грязными).

РЕДАКТИРОВАТЬ: Через несколько месяцев я понял, что @DirtiesContext не так хорош. Он в основном сбрасывает все приложение, что может быть дорогостоящим. Кроме того, @DirtiesContext может не сбрасывать вашу базу данных в некоторых случаях в зависимости от того, как работает ваше приложение. Я предлагаю создать SQL-скрипт очистки, который запускается в разделе @BeforeAll или @AfterAll каждого тестового класса. Этот SQL-сценарий очистки требует тщательного написания.

person user952342    schedule 31.05.2019
comment
AbstractIntegrationTest запускает Postgres в блоке статической инициализации, этот экземпляр базы данных будет единственным для всего вашего набора тестов, использование DirtiesContext не даст вам чистой базы данных после удаления контекста Spring в кеш. В этом случае вам нужно провести некоторую самостоятельную подготовку, чтобы очистить неправильные данные в postgres. - person Anatoliy Korovin; 08.06.2019
comment
Хорошая точка зрения. В нашем приложении весенней загрузки во время запуска есть сценарий для очистки базы данных как часть запуска ... так что да, это может не сработать для всех. Другие могут захотеть очистить свою базу данных после деструктивного теста с аннотацией, например: @Sql (scripts = {classpath: CleanUpDatabase.sql}) - person user952342; 10.06.2019

вы либо используете аннотацию @Before, чтобы очистить все перед выполнением тестов.

Или вы чистите в каждом тесте перед выполнением.

Каждый тест должен быть независимым от другого. Так обычно:

  • очистить и настроить ожидания
  • запустить тест

Если проверка завершится неудачно, ваша база данных перейдет в состояние сбоя, чтобы вы могли проверить, что произошло.

person Toerktumlare    schedule 29.05.2019