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 }