skyho
skyho

Reputation: 1903

liquibase.exception.MigrationFailedException: Migration failed for change set - Error during database initialization for all integration tests

I have a lot of integration tests and I have set up liquibase so that the database can be initialized. But each test class initializes a new initialization. In this case, duplicate data errors are unavoidable. I found a few recommendations to avoid this, but ran into a problem.

<databaseChangeLog
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
  xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.8.xsd">

  <changeSet author="n" context="test" id="1" runOnChange="false">
    <sqlFile encoding="utf8" endDelimiter="\nGO" path="classpath:dump.sql" relativeToChangelogFile="false"/>
  </changeSet>
</databaseChangeLog>
<databaseChangeLog
        xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
      http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.8.xsd">

    <include file="xml/changelog-1.xml" relativeToChangelogFile="true"/>


</databaseChangeLog>

I have also written a configuration class .

In the package :

public class CleanUpDatabaseTestExecutionListener extends AbstractTestExecutionListener {

    @Autowired
    SpringLiquibase liquibase;

    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE;
    }

    @Override
    public void afterTestClass(TestContext testContext) throws Exception {
        testContext.getApplicationContext()
                .getAutowireCapableBeanFactory()
                .autowireBean(this);
        liquibase.afterPropertiesSet();
    }
}
@Slf4j
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@TestExecutionListeners(listeners = {
        DependencyInjectionTestExecutionListener.class,
        TransactionalTestExecutionListener.class,
        CleanUpDatabaseTestExecutionListener.class,
})
public abstract class AbstractTestcontainers extends ContainerConfig {

I get an error: liquibase.exception.MigrationFailedException: Migration failed for change set db/changelog/test/liquibase-initdb.xml::1::n: Reason: liquibase.exception.DatabaseException: ERROR: type "calc_types" already exists [Failed SQL: (0) -- -- PostgreSQL database dump

spring.liquibase.drop-first=true - It doesn't work.

Maybe who know how can i correct this ?

Upvotes: 3

Views: 22082

Answers (1)

skyho
skyho

Reputation: 1903

At the moment, I did this

@Slf4j
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public abstract class AbstractTestcontainers extends ContainerConfig{

    @DynamicPropertySource
    private static void dynamicProperties(DynamicPropertyRegistry registry) {
        
        registry.add("spring.datasource.url", postgreSQLContainer::getJdbcUrl);
        registry.add("spring.datasource.username", postgreSQLContainer::getUsername);
        registry.add("spring.datasource.password", postgreSQLContainer::getPassword);
    }
}

I had to give up on:

@DirtiesContext(classMode = ClassMode.BEFORE_CLASS)

public abstract class ContainerConfig {

    protected static final PostgreSQLContainer postgreSQLContainer;

    static {

        DockerImageName postgres = DockerImageName.parse("postgres:11.7");

        postgreSQLContainer = (PostgreSQLContainer) new PostgreSQLContainer(postgres)
                .withDatabaseName("test")
                .withPassword("root")
                .withUsername("root")
                .withReuse(true);

        postgreSQLContainer.start();
    }

}

I had to leave over some classes

@Sql(executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, scripts = "classpath:createUsers.sql")
public class SomeClassRestTest extends AbstractTestcontainers {

to clear the tables and fill them with new data.

Liquibase configuration is run once, I at least didn't see any more conflicts. Since we have made one class that raises the context and all the other integration tests are performed using this context. Of course, the test classes themselves are incorrectly made, there it was necessary, using the @AfterClass or @AfterMethod annotations, to clear data from the databases. But nevertheless, now the execution of about 300 tests has been reduced by about 4 times.

If there are other solutions to this problem, please write.

Upvotes: 0

Related Questions