如何调试等待 React.lazy 导入超时的测试

Ago*_*gos 5 testing dynamic-import reactjs react-testing-library vitest

我有一个React+vite应用程序,我正在为其编写测试以涵盖应用程序启动时的前端路由重定向逻辑。

路由由 v6 处理react-router,所有与路由相关的组件都包装在React.lazy. 测试是由运行的vitest,我正在使用react-testing-library助手

所有测试都是相似的,看起来像这样

it('Redirects from app root to red room if the user has a red shirt', async () => {
    getUser.mockReturnValue(redShirtUser);
    render(MyTestedComponent, { wrapper });

    await waitFor(() => expect(screen.getByText('Welcome to the red room'));
    expect(history.location.pathname).toBe('/red-room');
  });
Run Code Online (Sandbox Code Playgroud)

然而,其中一项测试花费的时间比其他测试要长得多,甚至waitFor超时。我可以指定更长的超时waitFor,但它仍然无法在 CI 上可靠地运行。如果测试是其文件中唯一的测试/唯一正在执行的测试,也会发生这种情况。

我已经将缓慢的部分(通过调试的魔力console.log)缩小为惰性import()语句 - 导入并执行模块需要花费很多时间(秒)。

我该如何调试这个?是否有已知的因素会导致(惰性)导入变慢?

zor*_*404 5

Node的模块解析非常慢。因此,如果您的脚本导入/需要大量其他脚本/依赖项,那么您的启动时间将会非常慢。

如果您在测试中进行延迟导入,那么此启动时间将被计为测试的一部分。

您可以通过在测试文件顶部或设置阶段预加载脚本来避免这种情况。

在文件顶部预加载脚本是最简单的方法,
只需放置import './path';require('./path');

仅当您经常运行一些选定的测试而不是所有测试时,启动阶段的预加载才有用,因为您不想预加载不会被测试的脚本。

jest是使用beforeAll()如下方式完成的:

describe('my thing', () =>
{
    beforeAll(() => import('./path'))

    // alternatively you can use require:
    beforeAll(() => require('./path'))

    // ...your tests...
})
Run Code Online (Sandbox Code Playgroud)

我从未使用过vitest,所以我不知道那里的设置阶段是如何配置的。我只找到了这个,但这看起来像一个全局配置,最好将导入放在测试脚本的顶部,然后在全局配置中执行它。


附注:

如果组件需要几秒钟的时间才能加载,则可能表明它正在导入不需要的内容。
当同一个文件中有很多组件或者不将共享代码移动到单独的文件中时,通常会发生这种情况。
在 1 个文件中包含大量不相关的代码对于 Node 来说是一个问题,因为它无法进行任何树摇动,并且不会跳过未使用的导入。

此外,如果您的组件并不总是渲染其所有子组件,那么您也可以对这些子组件使用延迟导入。