React复制组件setTimeout逻辑导致分支覆盖率不足,如何编写测试覆盖
问题原因
你当前的测试没有触发setTimeout内部的回调函数,测试执行完成时5秒倒计时还没到,这部分代码从未运行,所以覆盖率统计未达标。
解决方案
使用Jest提供的假定时器能力,在测试中快进时间触发回调执行即可,修改测试代码如下:
首先在describe块新增定时器初始化和清理逻辑:
describe('A component test', () => { const props = { text: 'mock', }; // 每个测试用例前启用假定时器 beforeEach(() => { jest.useFakeTimers(); }); // 每个测试用例后恢复真实定时器,清理mock afterEach(() => { jest.useRealTimers(); jest.clearAllMocks(); }); // 修改后的复制成功测试用例 it('should copy to clipboard as expected', async () => { const mockWriteText = jest.fn().mockResolvedValueOnce(); Object.defineProperty(navigator, 'clipboard', { configurable: true, value: { writeText: mockWriteText, }, }); const renderedModule = mount(<A {...props} />); renderedModule.find('button').simulate('click'); // 等待复制成功的异步逻辑执行完成 await Promise.resolve(); expect(mockWriteText).toBeCalledTimes(1); // 原用例中'expectedCopy'和props的'mock'不一致,按需修改即可 expect(mockWriteText).toHaveBeenCalledWith(props.text); // 快进所有定时器,触发setTimeout回调 jest.runAllTimers(); renderedModule.update(); // 可选:如果组件有渲染copyStatus对应的提示,可加断言验证状态已重置 // 示例:expect(renderedModule.text()).not.toContain('复制成功') }); // 修改后的复制失败测试用例 it('should throw error on attempt to copy to clipboard', async () => { const mockWriteText = jest.fn().mockRejectedValue(new Error()); Object.defineProperty(navigator, 'clipboard', { configurable: true, value: { writeText: mockWriteText, }, }); // 原用例组件名写错了,是A不是CopyLink const renderedModule = mount(<A {...props} />); renderedModule.find('button').simulate('click'); await Promise.resolve(); expect(mockWriteText).toBeCalledTimes(1); // 注意:原组件没有渲染div.error的逻辑,这个断言需要补全组件渲染逻辑后保留,或者修改为验证copyStatus状态 // 示例:expect(renderedModule.state('copyStatus')).toEqual('no') }); });
额外注意
你的原组件返回逻辑有错误,CopyBtn是组件定义没有执行,实际运行会报错,需要修改为:
// 原错误写法 return (<div> {CopyBtn} </div>); // 修改后 return (<div> <CopyBtn /> </div>);
内容的提问来源于stack exchange,提问作者stacky
相关产品推荐
相关产品推荐

