React依赖状态的useEffect的Jest测试问题及报错解决
问题:用Jest测试依赖状态的useEffect,解决
useState.mockImplementation is not a function报错 我写了一段依赖状态的useEffect用于修改状态,代码如下:
useEffect(()=>{ if(open) { setOpen(false); } },[open]); // open是通过setOpen(true/false)修改的状态变量
代码覆盖率显示这段代码未被覆盖,需要用Jest测试它,且项目限制不能使用Enzyme。
我尝试了以下测试代码:
beforeAll(()=>{ useState.mockImplementation(callback=>{ return callback({ open:true }) }) }); test("Check State",async ()=>{ render(<ControlToRender/>); await act(()=> expect(open).toBe(false); })
执行npm run test时出现报错:
useState.mockImplementation is not a function
解决方法
1. 正确Mock React的useState
默认情况下Jest不会自动Mock React内置Hook,不能直接调用useState.mockImplementation。需要用jest.spyOn来Mock useState,同时捕获setOpen方法:
import React, { useState } from 'react'; import { render } from '@testing-library/react'; import ControlToRender from './ControlToRender';
2. 编写正确的测试逻辑
你的useEffect逻辑是:当open为true时,调用setOpen(false)。测试需要验证这个行为:
test("当open为true时,useEffect自动将其设为false", () => { // Mock useState,初始值设为true,同时保存mock的setOpen函数 const mockSetOpen = jest.fn(); jest.spyOn(React, 'useState').mockReturnValue([true, mockSetOpen]); // 渲染组件,此时useEffect会触发 render(<ControlToRender />); // 验证setOpen是否被调用,且传入的参数是false expect(mockSetOpen).toHaveBeenCalledWith(false); });
3. 测试后清理Mock(推荐)
为了避免Mock影响其他测试用例,在每个测试结束后恢复原有的useState:
afterEach(() => { jest.restoreAllMocks(); });
错误原因说明
- 直接调用
useState.mockImplementation无效,因为useState未被Jest Mock,只有通过jest.spyOn或jest.mock处理后,才会具备mockImplementation方法。 - 原测试中
act的用法错误,act应包裹触发状态更新的操作,而非断言语句。
内容的提问来源于stack exchange,提问作者C Sharper
相关产品推荐
相关产品推荐

