Jest Mock返回undefined而非预期值,如何正确模拟依赖函数?
问题:Jest模拟依赖的getFrames函数返回undefined导致测试报错
我在用Jest测试React组件,尝试模拟第三方依赖里的getFrames函数,期望它返回一个数组,但控制台显示返回undefined,触发报错:
TypeError: Cannot read property 'filter' of undefined
相关代码文件
ExitAppButton.tsx(点击按钮时调用依赖函数获取Frames列表)
import React, { useContext, useState } from 'react'; import { TestContext } from '../ContextProvider'; import { useDispatch } from 'react-redux'; const ExitAppButton = (props: any): JSX.Element => { const { sdkInstance } = useContext(TestContext); const exitAppClicked = () => { const appList = sdkInstance.getFrames().filter((app: any) => {app.appType === "Test App"}).length}
测试文件SignOutOverlay.test.tsx
import * as React from 'react'; import { fireEvent, render, screen } from '@testing-library/react'; import SignOutOverlay from '.'; import ExitAppButton from './ExitAppButton'; import { TestContext } from '../ContextProvider'; import { Provider } from 'react-redux'; import configureStore from 'redux-mock-store'; const api = require('@praestosf/container-sdk/src/api'); const mockStore = configureStore([]); jest.mock('@praestosf/container-sdk/src/api'); api.getFrames.mockReturnValue([{appType:"Test App"},{appType:"Test App"},{appType:"Not Test App"}]); describe('Test Exit app Button', () => { const renderExitAppButton = () => { const store = mockStore([{}]); render( <Provider store={store}> <TestContext.Provider value={{ sdkInstance: api }}> <SignOutOverlay> <ExitAppButton/> </SignOutOverlay> </TestContext.Provider> </Provider> ); }; it('should to be clicked and logged out', () => { renderExitAppButton(); fireEvent.click(screen.getByTestId('exit-app-button-id')); });
依赖文件api.js
const getFrames = () => { let frames = window.sessionStorage.getItem('TestList'); frames = frames ? JSON.parse(frames) : []; return frames }; const API = function () { }; API.prototype = { constructor: API, getFrames }; module.exports = new API();
问题分析与解决方案
你的模拟方式不正确,核心原因是:依赖导出的api是API类的实例,getFrames是挂载在类的原型链上的方法,而非实例自身的属性。你直接给api.getFrames赋值mock函数,不会覆盖原型上的方法,调用时仍然会执行原方法(测试环境中window.sessionStorage可能未被初始化,导致返回undefined)。
修正方案1:模拟原型上的getFrames方法
将测试代码中api.getFrames.mockReturnValue(...)替换为:
api.constructor.prototype.getFrames.mockReturnValue([{appType:"Test App"},{appType:"Test App"},{appType:"Not Test App"}]);
通过api.constructor获取API类,修改其原型上的getFrames方法,就能覆盖所有实例的调用行为。
修正方案2:自定义jest.mock直接模拟导出实例
将jest.mock('@praestosf/container-sdk/src/api');替换为自定义模拟:
jest.mock('@praestosf/container-sdk/src/api', () => { return { getFrames: jest.fn().mockReturnValue([{appType:"Test App"},{appType:"Test App"},{appType:"Not Test App"}]) }; });
这种方式直接让Jest用你定义的对象替代原模块的导出,实例上的getFrames就是你模拟的函数。
额外注意点
你的ExitAppButton代码中,filter的回调函数缺少返回值(虽然不是当前报错的原因,但会导致过滤结果错误),需修正为:
const appList = sdkInstance.getFrames().filter((app: any) => app.appType === "Test App").length
或保留大括号并添加return:
const appList = sdkInstance.getFrames().filter((app: any) => { return app.appType === "Test App" }).length
内容的提问来源于stack exchange,提问作者Tian Qin
相关产品推荐
相关产品推荐

