为什么我的反应测试在 CI 管道中由于“未包装在 act() 中”而失败,而在本地工作正常?

Lar*_*han 6 testing reactjs gitlab-ci jestjs react-testing-library

我有一个测试套件,其中包含 37 个测试,正在测试我的一个观点。在本地,所有测试都通过,没有任何问题,但是当我推送代码时,测试套件在我们的管道中失败(我们正在使用 GitLab)。

CI 中日志的错误输出非常长(数千行,甚至超过了 GitLab 设定的限制)。该错误由许多“未包含在 act() 中”和“不支持对 act() 的嵌套调用”警告组成(Moslty 由useTranslation()I18Next 和TooltipMaterial-UI 等组件触发)。

我的猜测是,来自 API 的异步数据(使用 msw 模拟)会在调用完成后触发状态更新act(),但我不确定如何证明这一点,甚至不知道哪些测试实际上失败了。

有没有人经历过类似的事情,或者知道是怎么回事?

失败测试的示例:

it.each([
    [Status.DRAFT, [PAGE_1, PAGE_11, PAGE_2, PAGE_22, PAGE_3]],
    [Status.PUBLISHED, [PAGE_1, PAGE_12, PAGE_2, PAGE_21, PAGE_22, PAGE_221]],
  ])('should be possible to filter nodes by status %s', async (status, expectedVisiblePages) => {
    renderComponent();
    await waitFor(() => {
      expect(screen.queryByRole('progressbar')).not.toBeInTheDocument();
    });
    userEvent.click(screen.getByLabelText('components.FilterMenu.MenuLabel'));
    const overlay = await screen.findByRole('presentation');
    await waitFor(() => expect(within(overlay).queryByRole('progressbar')).not.toBeInTheDocument());
    userEvent.click(within(overlay).getByText(`SiteStatus.${status}`));
    userEvent.keyboard('{Esc}');
    
    const items = await screen.findAllByRole('link');
    expect(items).toHaveLength(expectedVisiblePages.length);
    expectedVisiblePages.forEach((page) => expect(screen.getByText(page.title)).toBeInTheDocument());
  });
Run Code Online (Sandbox Code Playgroud)

更新1

好的。所以我将其范围缩小到这一行:

    const items = await screen.findAllByRole('link');
Run Code Online (Sandbox Code Playgroud)

在等待事情出现的过程中,似乎有很多事情正在发生。我相信对的调用findAllByRole已经包含在内act(),这将确保所有更新都已应用。

更新2

这似乎是一个部分由测试超时引起的问题。waitFor(...)我相信在同一个测试中,除了运行速度慢之外,多次调用和find[All]By(...)调用都会超过测试的超时时间(默认为 5000 毫秒)。我尝试通过运行测试来调整此限制--testTimeout 60000。现在,一些测试正在通过。我仍在与“act()”警告作斗争。这些可能是由完全不同的问题引起的......

搜寻错误仍在继续……

Lar*_*han 5

经过多次尝试,我终于找到了答案。CI 服务器只有 2 个可用的 CPU,通过使用 ,而--maxWorkers=2 --maxConcurrent=2不是默认值运行测试--maxWorkers=100% --maxConcurrent=5,证明可以解决问题。