UI.access() 期间的更改不会在单元测试期间推送

Seb*_*tge 1 vaadin vaadin-testbench vaadin24

我有以下视图类:

@Route(value = NewsAdminView.ROUTE)
@RequiredArgsConstructor
public class NewsAdminView extends VerticalLayout {
    public static final String ROUTE = "";
    private final NewsService service;
    final Grid<News> grid = new Grid<>(News.class);

    @Override
    protected void onAttach(AttachEvent attachEvent) {
        addComponents();

        service.getNews().subscribe(items -> updateItems(attachEvent.getUI(), items));
    }

    private void updateItems(final UI ui, final List<News> news) {
        ui.access(() -> {
            grid.setItems(news);
            grid.setEnabled(true);
        });
    }

    // Some details are omitted, like setting up the components and handling security, locale & URL parameters
}
Run Code Online (Sandbox Code Playgroud)

该服务执行 GraphQL 查询,该查询返回 Mono<List>,完成后将新闻条目添加到页面。AppShellConfigurator 具有必要的 @Push 注释,一旦在浏览器中部署和测试,整个设置就可以工作。

但我也有这个单元测试,扩展了 Vaadin TestBench 单元测试:

class NewsAdminViewTest extends VaadinUnitTest { // VaadinUnitTest extends Vaadin's SpringUIUnitTest
    @MockBean
    private NewsService service;

    @BeforeEach
    void setUp() {
        news = News.builder().build();
        when(service.getNews()).thenReturn(Mono.just(List.of(news)));
    }

    @Test
    void openWithNoParameters() {
        final NewsAdminView view = navigate(NewsAdminView.ROUTE, NewsAdminView.class);

        assertThat(view.grid.isVisible()).isTrue();
        assertThat(view.grid.isEnabled()).isTrue();
        assertThat(view.grid.getDataProvider().size(new Query<>())).isEqualTo(1);
    }
Run Code Online (Sandbox Code Playgroud)

调试时,我可以看到我的updateItems()方法被调用,模拟服务返回新闻条目的模拟列表,并且项目已设置且网格已启用。但是,一旦调用access()完成,并且应将更改推送到客户端,该步骤就会被跳过。VaadinSession.unlock()被调用,但VaadinSession.getUIs()为空。enabled并且状态和显示的网格行数的断言失败。

这是单元测试尚不支持的东西,还是我的应用程序或测试设置中缺少某些东西?

Mar*_*sny 5

原因是测试方法持有 UI 锁。UI锁只有在测试函数结束时才会释放,这基本上推迟了ui.access()测试函数结束后的所有调用,到那时就为时已晚了。

解决方案是在测试函数中暂时释放UI锁,然后重新获取它。您可以通过调用适当的 Vaadin 函数自己完成此操作,但还有更好的方法。Vaadin UI 测试基于Karibu-Testing,您也可以调用 Karibu 的函数。

请参阅Karibu-Testing 异步文档了解更多详细信息;这MockVaadin.clientRoundtrip()是关键。