React+Testing-Library测试报错:无法读取null的_location属性
测试用例全部通过但仍抛出TypeError,导致CI返回错误码1
错误现象
本地及GitHub Actions执行测试时,所有测试用例均通过,但测试结束后会抛出TypeError: Cannot read properties of null (reading '_location'),最终导致进程退出码为1,CI流程失败。
错误栈信息
TypeError: Cannot read properties of null (reading '_location') at Window.get location [as location] (my_files\characterbuilder\node_modules\jest-environment-jsdom\node_modules\jsdom\lib\jsdom\browser\Window.js:375:79) at FetchInterceptor.<anonymous> (my_files\characterbuilder\node_modules\@mswjs\interceptors\src\interceptors\fetch\index.ts:52:9) at step (my_files\characterbuilder\node_modules\@mswjs\interceptors\lib\interceptors\fetch\index.js:59:23) at Object.next (my_files\characterbuilder\node_modules\@mswjs\interceptors\lib\interceptors\fetch\index.js:40:53) at fulfilled (my_files\characterbuilder\node_modules\@mswjs\interceptors\lib\interceptors\fetch\index.js:31:58) at runNextTicks (node:internal/process/task_queues:60:5) at processImmediate (node:internal/timers:447:9)
GitHub Actions执行日志:
Run npm test > characterbuilder@0.1.0 test > react-scripts test PASS src/App.test.js App component ✓ renders race dropdown (140 ms) ✓ selects a race and renders subrace dropdown (141 ms) ✓ renders class dropdown (28 ms) ✓ selects a class and renders subclass dropdown (104 ms) ✓ rolls stats and displays rolled values (136 ms) ✓ selects class and checks if proficiencies are displayed correctly (72 ms) ✓ selects class and the max amount of proficiencies, then checks if selecting more proficiencies is allowed (74 ms) ✓ checks if proficiency checkboxes all start disabled when no class has been selected (36 ms) Test Suites: 1 passed, 1 total Tests: 8 passed, 8 total Snapshots: 0 total Time: 2.628 s Ran all test suites. /home/runner/work/characterbuilder/characterbuilder/node_modules/jest-environment-jsdom/node_modules/jsdom/lib/jsdom/browser/Window.js:375 return idlUtils.wrapperForImpl(idlUtils.implForWrapper(window._document)._location); ^ TypeError: Cannot read properties of null (reading '_location') at Window.get location [as location] (/home/runner/work/characterbuilder/characterbuilder/node_modules/jest-environment-jsdom/node_modules/jsdom/lib/jsdom/browser/Window.js:375:79) at FetchInterceptor.<anonymous> (/home/runner/work/characterbuilder/characterbuilder/node_modules/@mswjs/interceptors/src/interceptors/fetch/index.ts:52:9) at step (/home/runner/work/characterbuilder/characterbuilder/node_modules/@mswjs/interceptors/lib/interceptors/fetch/index.js:59:23) at Object.next (/home/runner/work/characterbuilder/characterbuilder/node_modules/@mswjs/interceptors/lib/interceptors/fetch/index.js:40:53) at fulfilled (/home/runner/work/characterbuilder/characterbuilder/node_modules/@mswjs/interceptors/lib/interceptors/fetch/index.js:31:58) at runNextTicks (node:internal/process/task_queues:60:5) at processImmediate (node:internal/timers:447:9) Node.js v18.16.0 Error: Process completed with exit code 1.
涉及的依赖文件代码
jest-environment-jsdom的Window.js中location属性逻辑
get location() { return idlUtils.wrapperForImpl(idlUtils.implForWrapper(window._document)._location); }
@mswjs/interceptors的fetch拦截器核心代码片段
protected checkEnvironment() { return ( typeof globalThis !== 'undefined' && typeof globalThis.fetch !== 'undefined' ) } protected setup() { const pureFetch = globalThis.fetch invariant( !(pureFetch as any)[IS_PATCHED_MODULE], 'Failed to patch the "fetch" module: already patched.' ) globalThis.fetch = async (input, init) => { const request = new Request(input, init) const url = typeof input === 'string' ? input : input.url const method = request.method this.log('[%s] %s', method, url) const body = await request.clone().arrayBuffer() const requestUrl = new URL( url, typeof location !== 'undefined' ? location.origin : undefined ) // 后续业务逻辑省略 }
GitHub Actions工作流配置
name: Continuous Integration on: push: branches: - dev jobs: build: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v2 - name: Install dependencies run: npm ci - name: Install run: npm install - name: run tests run: npm test
已尝试的解决方案
- 在
setupTests.js中添加window.URL.createObjectURL = function () {};和jest.spyOn(window, "close").mockImplementation(jest.fn()); - 简化测试用例,仅保留无实际逻辑的单测试用例,问题仍未解决
注:未修改任何依赖文件,项目核心代码位于dev分支,业务代码在App.js,测试文件为App.test.js,Mock服务器配置在setupServer.js。
内容的提问来源于stack exchange,提问作者marijnjc88
相关产品推荐
相关产品推荐

