Невозможно инициализировать БД для каждого метода тестирования при весенней загрузке. - PullRequest
0 голосов
/ 01 июля 2019

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

Из документов я узнал, что все, что мне нужно сделать, это добавить

@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)

в мой тестовый класс.

Я вижу из журналов, что это действительно запускает несколько контекстов приложения вместо одного.

Но кажется, что этот контекст инициализируется перед выполнением любого теста и фактически живет в JVM одновременно. Но я думаю, что они разделяют один экземпляр H2. В первый раз сценарий инициализации sql выполняется просто отлично, но затем я получаю Table already exists ошибок, потому что он пытается создать таблицы, которые уже есть.

Как я могу убедиться, что тесты, включая контекст приложения Spring и H2 DB, полностью seriazlied?

application.properties

server.port=8001

spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=sa
spring.jpa.show-sql=true
spring.jpa.generate-ddl=false
spring.jpa.hibernate.ddl-auto=none
spring.datasource.schema=classpath*:h2/ddl/infop-schemas.sql, \
  classpath*:h2/ddl/infop-tables-fahrplan.sql, \
  classpath*:h2/ddl/infop-tables-import.sql, \
  classpath*:h2/ddl/infop-tables-stammdaten.sql, \
  classpath*:h2/ddl/infop-tables-statistik.sql, \
  classpath*:h2/ddl/infop-tables-system.sql, \
  classpath*:h2/ddl/infop-tables-utility.sql, \
  classpath*:h2/ddl/infop-sequences.sql, \
  classpath*:h2/ddl/infop-views.sql \
  classpath*:h2/dll/infop-constraints-system.sql \
  classpath*:h2/dll/infop-constraints-stammdaten.sql \
  classpath*:h2/dll/infop-constraints-statistik.sql \
  classpath*:h2/dll/infop-constraints-import.sql \
  classpath*:h2/dll/infop-constraints-fahrplan.sql

Тестовый класс:

@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = {TestApplicationDao.class})
@ActiveProfiles("test")
@Transactional
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
public class ProtokollIntegrationTest {

    private static final Logger LOGGER = LoggerFactory.getLogger(ProtokollIntegrationTest.class);

    @Test
    public void thatMaxLaufnummerIsFound() {
        LOGGER.debug("thatMaxLaufnummerIsFound()");
        Optional<Protokoll> maxProtokollOpt = protokollRepository.findFirstByAuftragSchrittOrderByLaufnummerDesc(auftragSchritt);

        assertTrue(maxProtokollOpt.isPresent());
        assertEquals(new Integer(9), maxProtokollOpt.get().getLaufnummer());
    }

    @Test
    public void thatNoLaufnummerIsFound() {
        LOGGER.debug("thatNoLaufnummerIsFound()");
        AuftragSchritt as = new AuftragSchritt();
        as.setStatusCode(code);
        auftragSchrittRepository.save(as);

        Optional<Protokoll> maxProtokollOpt = protokollRepository.findFirstByAuftragSchrittOrderByLaufnummerDesc(as);

        assertFalse(maxProtokollOpt.isPresent());
    }

    @Test
    public void thatFindByAuftragSchrittWorksFine() {
        LOGGER.debug("thatFindByAuftragSchrittWorksFine()");
        List<Protokoll> protokollList = protokollRepository.findByAuftragSchritt(auftragSchritt);

        assertNotNull(protokollList);
        assertEquals(10, protokollList.size());
    }

}

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.compay.my-prj</groupId>
    <artifactId>my-prj-dao</artifactId>
    <version>0.2.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.4.RELEASE</version>
    </parent>

    <properties>
        <java.version>1.8</java.version>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.build.timestamp.format>yyyy-MM-dd HH:mm</maven.build.timestamp.format>
        <timestamp>${maven.build.timestamp}</timestamp>
        <junit.jupiter.version>5.4.2</junit.jupiter.version>
        <junit.platform.launcher.version>1.4.2</junit.platform.launcher.version>
        <my-prj.version>8.25.0</my-prj.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.9</version>
        </dependency>
        <dependency>
            <groupId>com.compay.my-prj</groupId>
            <artifactId>my-prj-common-entity</artifactId>
            <version>${my-prj.version}</version>
            <classifier>hibernate</classifier>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <!-- wir werden junit5 verwenden (unten) -->
                <exclusion>
                    <groupId>junit</groupId>
                    <artifactId>junit</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.compay.my-prj</groupId>
            <artifactId>my-prj-dao-test</artifactId>
            <version>0.5.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.compay.my-prj</groupId>
            <artifactId>my-prj-common-entity-test</artifactId>
            <version>${my-prj.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>2.0.1.Final</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>${junit.jupiter.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-launcher</artifactId>
            <version>${junit.platform.launcher.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-source-plugin</artifactId>
                <executions>
                    <execution>
                        <id>attach-sources</id>
                        <goals>
                            <goal>jar</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <!-- für junit5 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.22.2</version>
            </plugin>
        </plugins>
    </build>
</project>

Выход журнала см. https://1drv.ms/t/s!AnJdkNZlKN5ygVi72qB6wL1KOcpZ (извините, это слишком для SO)

Ответы [ 2 ]

0 голосов
/ 04 июля 2019

После всего этого оказалось отсутствие зависимости!

у меня не было

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional>
    </dependency>

Это приводит к тому, что автоконфигурация сводит с ума и делает такие вещи, как инициализация контекста приложения в неправильном порядке и другие извращенные вещи. К сожалению, это не выдает никаких сообщений об ошибках или предупреждений вообще.

Итак, обучение:

Если в вашем коде @DirtiesContext, вы должны добавить spring-boot-devtools к вашим зависимостям.

0 голосов
/ 01 июля 2019

В обычном сценарии JPA / Hibernate, где spring.jpa.hibernate.ddl-auto установлен на create-drop и DirtiesContext установлен на BEFORE_EACH_TEST_METHOD, это сработало бы, так как jpa / hibernate попытается сначала удалить все таблицы и снова создать все таблицыпосле каждого выполнения теста.Сценарий Create / DROP, обрабатываемый hibernate (что не происходит в вашем случае)

Но в соответствии с вашими настройками, т.е. DirtiesContext = BEFORE_EACH_TEST_METHOD и spring.datasource.schema = <multiple-sql-files>, таблицы создаютсяваши сценарии, но не сбрасываются.Из-за этого вы получаете ошибку Table already exists.

Я бы порекомендовал вам добавить еще один файл SQL в начале , который состоит из запросов на удаление всех созданных таблиц / представлений, если таковые существуют.Это точно решит вашу проблему.

...