You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Testing Library测试过慢,求排查原因

问题:Create React App构建的大型SPA组件测试耗时过长是否正常?原因是什么?

我们公司有一个2020年用Create React App构建的大型单页应用,目前几乎所有组件的测试耗时都过长,有时超过300秒,有时100秒,最快也需要30秒。请问这种情况正常吗?若不正常,导致测试耗时久的原因是什么?

测试耗时截图

测试代码示例(无法复现问题,供排查参考)

// required imports from React & 3rd party libraries
import React from 'react';
import { render, screen, within } from '@testing-library/react';
import { API } from 'aws-amplify';

// react component to be tested, plus context and helper functions
import { MyComponent } from './MyComponent';
import { Store, UserContext, FurtherDetailContext } from 'store/store';
import * as helpers from 'helpers';

// mock data
import userContextMock from '../../../tests/fixtures/userContext/userContext.json';
import furtherDetailContextMock from '../../../tests/fixtures/furtherDetailContext/furtherDetailContext.json';
import gqlQueryResponse1 from '../../../tests/fixtures/gql/gqlQueryResponse1.json';
import gqlQueryResponse2 from '../../../tests/fixtures/gql/gqlQueryResponse2.json';
const mockJson = {
    this: 'is',
    an: 'example',
    response: true
};

const arrange = async () => {
    const mockToggleOpen = jest.fn();
    render(
        <Store>
            <UserContext.Provider
                value={{
                    userContext: userContextMock,
                    setUserContext: () => {
                        // do nothing
                    }
                }}>
                <FurtherDetailContext.Provider
                    value={{
                        furtherDetailContext: furtherDetailContextMock,
                        setFurtherDetailContext: () => {
                            /*do nothing */
                        }
                    }}>
                    <MyComponent myProps={mockJson} toggleOpen={mockToggleOpen} />
                </FurtherDetailContext.Provider>
            </UserContext.Provider>
        </Store>
    );

    // this component performs a network request before rendering
    await screen.findByText('text on the screen');
    const testid1 = screen.getByTestId('test-id-example');
    const testid2 = screen.getByTestId('test-id-example-2');
    return { testid1, testid2 };
};

describe('MyComponent', () => {
    beforeEach(() => {
        // get auth token
        jest.spyOn(helpers, 'getAuthtoken').mockResolvedValue('validAuthToken');
    });
    describe('all calls mocked', () => {
        beforeEach(() => {
            // mock graphql requests
            API.graphql = jest.fn().mockImplementation((url) => {
                const gqlQuery = url.query;
                if (RegExp('.*.mockGqlQuery*').test(gqlQuery)) {
                    return gqlQueryResponse1;
                }
                if (RegExp('.*.mockGql2*').test(gqlQuery)) {
                    return gqlQueryResponse2;
                }

                return;
            });
        });

        it('shows the original text on component mount', async () => {
            const { testid1 } = await arrange();
            expect(within(testid1).getByText('this text should be here')).toBeInTheDocument();
        });
    });
});

相关依赖版本

"dependencies": {
  "@types/node": "^12.12.50",
  "@types/react": "^17.0.52",
  "@types/react-dom": "^17.0.18",
  "@types/react-router-dom": "^5.1.7",
  "@types/react-leaflet": "^2.8.1",
  "aws-amplify": "^4.3.26",
  "leaflet": "^1.7.1",
  "react": "^17.0.1",
  "react-dom": "^17.0.1",
  "react-leaflet": ">=3.1.0 <3.2.0 || ^3.2.1",
  "@react-leaflet/core": ">=1.0.0 <1.1.0 || ^1.1.1",
  "react-router-dom": "^6.4.3",
  "typescript": "^3.7.5",
}
"devDependencies": {
  "react-scripts": "^5.0.1",
  "@testing-library/dom": "^7.28.1",
  "@testing-library/jest-dom": "^5.11.6",
  "@testing-library/react": "^12.1.5",
  "@testing-library/user-event": "^13.5.0",
  "@types/jest": "^26.0.4",
  "jest": "^26.6.3",
  "node-sass": "^6.0.1",
}

本地开发Node.js版本:v16.15.1


回答

这种测试耗时完全不正常。即便是大型SPA,单个组件测试也不该超过几秒,全量测试通常也能控制在几分钟内。结合你的代码和依赖信息,可能的原因包括以下几点:

1. 测试未真正隔离外部依赖

  • 你虽然mock了API.graphql和getAuthtoken,但Store组件可能包含未被mock的全局逻辑(比如Redux store真实初始化、副作用执行),导致测试加载不必要的全局状态或执行额外操作。
  • Leaflet这类第三方地图组件,在测试环境中可能触发真实DOM渲染或计算,需用jest.mock完全替换为占位组件,避免真实逻辑运行。

2. Jest配置与版本问题

  • jest 26.6.3和react-scripts 5.0.1存在兼容性问题:react-scripts 5默认适配jest 27+,低版本jest处理现代React组件和TypeScript代码的效率更低。
  • 未开启Jest缓存或缓存频繁失效,导致每次测试都重新编译所有文件。
  • 测试未并行执行:大型项目若禁用了Jest默认的并行测试,会导致测试逐个运行,耗时累加。

3. 测试写法低效

  • await screen.findByText默认超时时间较长(1000ms),若组件渲染慢或mock响应不及时,会等待满超时才继续,可明确设置更短超时时间或确保mock同步返回结果。
  • 每个测试用例重复渲染完整上下文(Store、多层Context),未复用渲染逻辑或用轻量替身替换复杂上下文。
  • 未清理jest mock:beforeEach中设置的mock若未在afterEach恢复,会导致测试用例间相互影响,出现不必要的等待或错误。

4. 依赖包版本不匹配

  • React Router DOM v6.4.3与@types/react-router-dom v5.1.7版本不匹配,类型定义和实际代码的差异会导致测试时额外的类型检查或运行时开销。
  • TypeScript 3.7.5版本较老,对现代React语法的编译效率低,且与新版react-scripts存在兼容问题。

5. 本地环境因素

  • Node.js v16.15.1虽稳定,但Jest在Node 18+版本中有性能优化,旧版本Node可能导致测试运行效率偏低。
  • 本地机器资源不足(内存、CPU),或测试时同时运行其他占用资源的程序,导致测试卡顿。

内容的提问来源于stack exchange,提问作者mjwebson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 02:07:05