使用Jest与Provider组件在React测试中无法注入MobX Store
问题描述
我在为React组件编写单元测试时,需要将MobX Store的某个属性设置为非默认状态。尝试修改状态后通过<Provider>注入组件,但测试中该属性值始终为false,各种模拟/替换Store的方法都没生效。
Store代码
export class ModalControlStore { root: RootStore; constructor(root: RootStore) { this.root = root; makeAutoObservable(this); } modalIsOpen = false; setModalIsOpen(isModalOpen: boolean) { this.modalIsOpen = modalIsOpen } }
组件中获取Store的代码
export function useModalControlStore() { const { modalControlStore } = useRootStore(); return modalControlStore ; }
组件中使用Store的方式
const { modalIsOpen } = useModalControlStore();
当前测试代码
beforeEach(() => { const modalControlStore = useModalControlStore(); modalControlStore.setModalIsOpen(true); render( <Provider modalControlStore={modalControlStore}> <PopUpModal/> </Provider> ) });
解决方案
你的测试代码存在两个核心问题:
- 在渲染组件前直接调用
useModalControlStore()违规:React Hooks只能在组件或自定义Hook内部调用,测试环境中直接调用会脱离Provider上下文,拿到的不是你要注入的目标Store实例。 - 未正确创建并注入自定义Store实例:需要手动创建
ModalControlStore实例(可模拟RootStore依赖),修改状态后再通过Provider注入组件。
修改后的测试代码示例(单Store注入)
// 模拟RootStore(按需补充实际依赖) const mockRootStore = {} as RootStore; beforeEach(() => { // 手动创建Store实例 const modalControlStore = new ModalControlStore(mockRootStore); // 设置目标状态 modalControlStore.setModalIsOpen(true); render( <Provider modalControlStore={modalControlStore}> <PopUpModal/> </Provider> ) });
若依赖RootStore全局注入
如果你的useRootStore是从全局RootStore Provider中获取实例,需注入完整的模拟RootStore:
// 模拟包含目标Store的RootStore const mockRootStore = { modalControlStore: new ModalControlStore({} as RootStore) } as RootStore; // 提前设置状态 mockRootStore.modalControlStore.setModalIsOpen(true); beforeEach(() => { render( <Provider rootStore={mockRootStore}> <PopUpModal/> </Provider> ) });
简化方案:直接Mock Hook
若使用Jest,可直接MockuseModalControlStore,返回预设状态的Store:
jest.mock('./path-to-useModalControlStore', () => ({ useModalControlStore: () => ({ modalIsOpen: true, setModalIsOpen: jest.fn() }) })); beforeEach(() => { render(<PopUpModal/>); });
内容的提问来源于stack exchange,提问作者user3822332
相关产品推荐
相关产品推荐

