4.9.1. Интеграционные тесты Middleware

Интеграционные тесты Middleware выполняются в полнофункциональном контейнере Spring с подключением к базе данных. В тестах такого типа можно выполнять код любого слоя внутри Middleware - от сервисов до ORM.

См. также руководство Middleware Integration Testing in CUBA Applications.

Сразу после создания нового проекта с помощью Studio, в базовом пакете модуля core находятся два класса: тестовый контейнер и пример теста. Класс тестового контейнера запускает контейнер Spring среднего слоя, настроенный для выполнения тестов. Пример теста использует этот контейнер и демонстрирует, как можно тестировать некоторые операции с сущностью.

Рассмотрим сгенерированный класс контейнера и пути его адаптации для нужд проекта.

Класс контейнера должен расширять класс TestContainer, предоставляемый CUBA. В конструкторе класса необходимо выполнить следующее:

  • Добавить в список appComponents все компоненты приложения (аддоны), используемые в проекте.

  • Если необходимо, указать дополнительные файлы свойств приложения в списке appPropertiesFiles.

  • Вызвать метод autoConfigureDataSource() для инициализации тестового источника данных по информации из свойств приложения или из context.xml.

Сгенерированный тестовый контейнер обеспечивает подключение к той же базе данных, с которой работает приложение. То есть ваши тесты будут выполняться на основном хранилище данных, даже если вы поменяете его тип или то, как задается его JDBC DataSource.

В использовании одной базы данных и для тестов, и для приложения, есть недостаток: данные, введенные вручную в приложении, могут мешать выполнению тестов, и наоборот. Чтобы избежать этого, для тестов можно использовать отдельную БД. Рекомендуется использовать СУБД такого же типа, что и для основной БД, так как в этом случае можно использовать один набор скриптов миграции БД. Ниже приведен пример настройки тестовой базы данных на локальном PostgreSQL.

Во-первых, добавьте задачу создания тестовой БД в build.gradle:

configure(coreModule) {
    // ...
    task createTestDb(dependsOn: assembleDbScripts, type: CubaDbCreation) {
        dbms = 'postgres'
        host = 'localhost'
        dbName = 'demo_test'
        dbUser = 'cuba'
        dbPassword = 'cuba'
    }

Затем создайте файл test-app.properties в базовом пакете корня тестов (например, modules/core/test/com/company/demo/test-app.properties) и укажите свойства подключения к тестовой БД:

cuba.dataSource.host = localhost
cuba.dataSource.dbName = demo_test
cuba.dataSource.username = cuba
cuba.dataSource.password = cuba

Добавьте этот файл в список appPropertiesFiles тестового контейнера:

public class DemoTestContainer extends TestContainer {

    public DemoTestContainer() {
        super();
        appComponents = Arrays.asList(
                "com.haulmont.cuba"
        );
        appPropertiesFiles = Arrays.asList(
                "com/company/demo/app.properties",
                "com/haulmont/cuba/testsupport/test-app.properties",
                "com/company/demo/test-app.properties" // your test properties
        );
        autoConfigureDataSource();
    }

Перед выполнением тестов создайте тестовую БД путем выполнения задачи:

./gradlew createTestDb

Тестовый контейнер используется в классах тестов в качестве JUnit 5 extension, указанного с помощью аннотации @RegisterExtension:

package com.company.demo.core;

import com.company.demo.DemoTestContainer;
import com.company.demo.entity.Customer;
import com.haulmont.cuba.core.entity.contracts.Id;
import com.haulmont.cuba.core.global.AppBeans;
import com.haulmont.cuba.core.global.DataManager;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class CustomerTest {

    // Using the common singleton instance of the test container which is initialized once for all tests
    @RegisterExtension
    static DemoTestContainer cont = DemoTestContainer.Common.INSTANCE;

    static DataManager dataManager;

    @BeforeAll
    static void beforeAll() {
        // Get a bean from the container
        dataManager = AppBeans.get(DataManager.class);
    }

    @Test
    void testCreateLoadRemove() {
        Customer customer = cont.metadata().create(Customer.class);
        customer.setName("c1");

        Customer committedCustomer = dataManager.commit(customer);
        assertEquals(customer, committedCustomer);

        Customer loadedCustomer = dataManager.load(Id.of(customer)).one();
        assertEquals(customer, loadedCustomer);

        dataManager.remove(loadedCustomer);
    }
}
Полезные методы тестового контейнера

Класс TestContainer содержит следующие методы, которые можно использовать в коде тестов (см. пример CustomerTest выше):

  • persistence() - возвращает ссылку на интерфейс Persistence.

  • metadata() - возвращает ссылку на интерфейс Metadata.

  • deleteRecord() - этот набор перегруженных методов предназначен для использования в @After методах для удаления тестовых объектов из БД.

Кроме того, ссылку на любой бин можно получить статическим методом AppBeans.get().

Логирование

Класс TestContainer настраивает логирование в соответствие с файлом test-logback.xml, предоставляемым платформой. Данный файл содержится в артефакте cuba-core-tests.

Для того, чтобы настроить уровни логирования в своих тестах, необходимо выполнить следующее:

  • Создайте файл my-test-logback.xml в каталоге test модуля core проекта. Вы можете взять за основу содержимое файла test-logback.xml, находящегося внутри артефакта cuba-core-tests.

  • Добавьте блок статической инициализации в класс тестового контейнера проекта и укажите местоположение файла конфигурации Logback в системном свойстве logback.configurationFile:

    public class DemoTestContainer extends TestContainer {
    
        static {
            System.setProperty("logback.configurationFile", "com/company/demo/my-test-logback.xml");
        }
Дополнительные хранилища

Если в вашем проекте используются дополнительные хранилища, и если тип дополнительной базы данных отличается от основной, необходимо добавить ее драйвер как testRuntime зависимость модуля core в build.gradle, например:

configure(coreModule) {
    // ...
    dependencies {
        // ...
        testRuntime(hsql)
        jdbc('org.postgresql:postgresql:9.4.1212')
        testRuntime('org.postgresql:postgresql:9.4.1212') // add this
    }