UI 集成测试

Jmix 支持为 UI 层编写测试。在这些测试中,可以打开视图、加载数据、验证 UI 组件的内容、修改组件内容以及模拟用户操作(例如,点击按钮)。

Jmix UI 测试会启动完整的 Spring 上下文,并且可以像业务逻辑的 集成测试 一样与数据库进行交互。从某种意义上说,Jmix UI 的集成测试更接近基于浏览器的端到端测试,因为可以测试应用程序的各种功能,但更加易于设置,执行速度也比基于浏览器的测试快得多。

每个新建的 Jmix 项目都包含一个 UI 集成测试的示例:'UserUiTest' 类,用于测试用户管理视图。我们通过此示例了解一下 UI 测试的配置和逻辑。

如需执行 UI 测试,项目需要依赖 jmix-flowui-test-assist 模块:

build.gradle
testImplementation 'io.jmix.flowui:jmix-flowui-test-assist'

测试类示例如下:

UserUiTest.java
package com.company.demo.user;

import com.company.demo.DemoApplication;
import com.company.demo.entity.User;
import com.company.demo.view.user.UserDetailView;
import com.company.demo.view.user.UserListView;
import io.jmix.core.DataManager;
import io.jmix.flowui.ViewNavigators;
import io.jmix.flowui.component.UiComponentUtils;
import io.jmix.flowui.component.grid.DataGrid;
import io.jmix.flowui.component.textfield.JmixPasswordField;
import io.jmix.flowui.component.textfield.TypedTextField;
import io.jmix.flowui.data.grid.DataGridItems;
import io.jmix.flowui.kit.component.button.JmixButton;
import io.jmix.flowui.testassist.FlowuiTestAssistConfiguration;
import io.jmix.flowui.testassist.UiTest;
import io.jmix.flowui.testassist.UiTestUtils;
import io.jmix.flowui.view.View;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

/**
 * Sample UI integration test for the User entity.
 */
@UiTest (1)
@SpringBootTest(classes = {DemoApplication.class, FlowuiTestAssistConfiguration.class}) (2)
public class UserUiTest {

    @Autowired
    DataManager dataManager; (3)

    @Autowired
    ViewNavigators viewNavigators;

    @Test (4)
    void test_createUser() {
        // Navigate to user list view
        viewNavigators.view(UserListView.class).navigate();

        UserListView userListView = UiTestUtils.getCurrentView(); (5)

        // click "Create" button
        JmixButton createBtn = findComponent(userListView, "createBtn"); (6)
        createBtn.click();

        // Get detail view
        UserDetailView userDetailView = UiTestUtils.getCurrentView();

        // Set username and password in the fields
        TypedTextField<String> usernameField = findComponent(userDetailView, "usernameField");
        String username = "test-user-" + System.currentTimeMillis();
        usernameField.setValue(username);

        JmixPasswordField passwordField = findComponent(userDetailView, "passwordField");
        passwordField.setValue("test-passwd");

        JmixPasswordField confirmPasswordField = findComponent(userDetailView, "confirmPasswordField");
        confirmPasswordField.setValue("test-passwd");

        // Click "OK"
        JmixButton commitAndCloseBtn = findComponent(userDetailView, "saveAndCloseBtn");
        commitAndCloseBtn.click();

        // Get navigated user list view
        userListView = UiTestUtils.getCurrentView();

        // Check the created user is shown in the table
        DataGrid<User> usersDataGrid = findComponent(userListView, "usersDataGrid");

        DataGridItems<User> usersDataGridItems = usersDataGrid.getItems();
        Assertions.assertNotNull(usersDataGridItems);

        usersDataGridItems.getItems().stream()
                .filter(u -> u.getUsername().equals(username))
                .findFirst()
                .orElseThrow();
    }

    @AfterEach (7)
    void tearDown() {
        dataManager.load(User.class)
                .query("e.username like ?1", "test-user-%")
                .list()
                .forEach(u -> dataManager.remove(u));
    }

    @SuppressWarnings("unchecked")
    private static <T> T findComponent(View<?> view, String componentId) {
        return (T) UiComponentUtils.getComponent(view, componentId);
    }
}
1 @UiTest 注解定义了一个 JUnit 扩展,用于启动 Vaadin、配置应用程序视图以及配置用户认证。
2 @SpringBootTest 注解需要声明应用程序和 jmix-flowui-test-assist 模块的配置。
3 可以用 @Autowired 注解注入 Spring bean。
4 测试用例的方法。
5 UiTestUtils.getCurrentView() 返回导航当前打开的视图。
6 findComponent() 可以按 ID 查找 UI 组件。
7 每个测试用例后执行该方法清理测试数据。