如何在React Testing Library中为测试场景mock Web Worker
Jest 环境 Mock Web Worker 解决方案
1. mock 文件夹的文件命名规则
你有两种可选的Mock方案,对应不同的命名规则:
- 如果你选择Mock封装了
getWebWorker的工具模块:假设getWebWorker定义在src/utils/worker.js文件中,你需要在同级目录新建__mock__/worker.js,Mock文件的名称必须和原工具文件的名称完全一致。 - 如果你选择直接Mock全局
WorkerAPI:不需要创建单独的__mock__文件,可以直接在测试用例文件或者Jest全局初始化文件(比如setupTests.js)中定义全局Mock即可。
2. Worker 的Mock实现示例
全局Worker Mock实现(更适配你的使用场景)
// 可以写在setupTests.js里全局生效,也可以写在单测试用例文件顶部 global.Worker = class MockWorker { constructor(path) { // 可以在这里判断路径匹配你的worker.js做特殊逻辑,非必需 this.path = path; // 挂载onmessage属性,承接业务代码中赋值的回调函数 this.onmessage = null; // Mock postMessage方法,如果你业务中会向worker发消息可以用来断言调用情况 this.postMessage = jest.fn(); // 提供一个主动触发消息的Mock方法,供测试用例调用模拟worker返回数据 this.mockTriggerMessage = (data) => { if (this.onmessage) { this.onmessage({ data }); } }; } }
工具模块Mock实现(如果你选择MockgetWebWorker所在的模块)
对应__mock__/worker.js的内容:
const mockWorkerInstance = { onmessage: null, postMessage: jest.fn(), mockTriggerMessage: (data) => { if (mockWorkerInstance.onmessage) { mockWorkerInstance.onmessage({ data }); } } }; export const getWebWorker = jest.fn(() => mockWorkerInstance);
3. 测试文件的额外操作
如果你用的是全局Worker Mock方案
你可以直接在测试用例中获取worker实例,触发消息回调验证逻辑:
import { render, screen } from '@testing-library/react'; import YourComponent from './YourComponent'; test('worker返回数据后正常渲染', () => { render(<YourComponent />); // 获取到实例化的MockWorker const workerInstance = global.Worker.mock.instances[0]; // 模拟worker返回测试数据 const mockTestData = { count: 10, name: '测试数据' }; workerInstance.mockTriggerMessage(mockTestData); // 验证你的业务逻辑是否正常执行,比如对应数据是否渲染到页面 expect(screen.getByText(mockTestData.name)).toBeInTheDocument(); });
如果你用的是工具模块Mock方案
需要先声明Mock对应模块,再做测试:
import { render, screen } from '@testing-library/react'; import { getWebWorker } from 'src/utils/worker'; import YourComponent from './YourComponent'; // 声明Mock该模块,Jest会自动读取__mock__下的对应文件 jest.mock('src/utils/worker'); test('worker返回数据后正常渲染', () => { render(<YourComponent />); // 获取Mock的worker实例 const mockWorker = getWebWorker.mock.results[0].value; // 模拟返回测试数据 const mockTestData = { count: 10, name: '测试数据' }; mockWorker.mockTriggerMessage(mockTestData); // 验证业务逻辑 expect(screen.getByText(mockTestData.name)).toBeInTheDocument(); });
补充说明:你当前写的
getWebWorker单例逻辑存在问题,worker变量定义在函数内部,每次调用函数都会重新初始化,无法实现单例效果,建议把let worker移到函数外部。
内容的提问来源于stack exchange,提问作者z0ccc
相关产品推荐
相关产品推荐

