如何使用Jest仅Mock Context Provider中的单个状态变量?
问题根源
你当前测试直接传入静态的emptyApi和修改后的defaultState作为Context值,emptyApi内的setStep是预先定义的空函数,没有绑定真实React状态,调用后自然不会触发状态更新,相当于完全抛弃了原Provider的内部逻辑。
解决方案
这里提供两种常用实现方式,都可以做到只mock userList 保留step相关逻辑:
方案1:复用原AppContextProvider,仅mock用户接口
该方式最贴近应用真实运行逻辑,所有原有状态逻辑100%保留,仅需要把获取用户的接口返回替换为mock数据即可:
import Progress from './progress' import { AppContextProvider } from './context/AppContext' import { render, screen } from "@testing-library/react" // 示例:假设你获取用户列表调用的是axios.get('/api/users'),直接mock该请求 jest.mock('axios', () => ({ ...jest.requireActual('axios'), get: jest.fn((url) => { if (url === '/api/users') { // 返回你需要的mock用户列表 return Promise.resolve({ data: [{id: 1, name: '测试用户1'}, {id: 2, name: '测试用户2'}] }) } return jest.requireActual('axios').get(url) }) })) describe('progress', () => { it('should go through the steps', async () => { render( // 直接使用原有的AppContextProvider,不要自定义传入静态value <AppContextProvider> <Progress /> </AppContextProvider> ) // 若组件初始化会调用callUsers,可等待接口返回完成再执行后续操作 // 此时step相关逻辑完全正常,调用setStep会真实更新状态触发重渲染 }) })
方案2:自定义测试专用Provider,直接传入mock用户列表
如果你不想mock接口,想要直接指定userList的值,可以写一个测试专用Provider,完全复用原Provider的step逻辑,仅把userList替换为你传入的固定值:
import Progress from './progress' import AppContext from './context/AppContext' import { render, screen } from "@testing-library/react" // 测试用自定义Provider,保留原step逻辑,支持传入mock用户列表 const TestAppContextProvider = ({ children, mockUserList = [] }) => { // 原Provider的step逻辑完全保留 const [stepNum, setStepNum] = React.useState(0); const api = { setStep: setStepNum, callUsers: () => {} // 不需要调用接口可留空,需要的话也可以保留原逻辑 } const state = { userList: mockUserList, // 直接使用传入的mock数据 step: stepNum, } return <AppContext.Provider value={{ api, state }}>{children}</AppContext.Provider> } describe('progress', () => { it('should go through the steps', () => { render( <TestAppContextProvider mockUserList={[{id: 1, name: '测试用户'}]}> <Progress /> </TestAppContextProvider> ) // 此时setStep调用会正常更新step状态,userList为你传入的mock值 }) })
注意
你代码中的React组件名progress为小写,React会将其识别为原生HTML标签,建议改为大写开头的Progress避免异常。
内容的提问来源于stack exchange,提问作者Aetos11
相关产品推荐
相关产品推荐

