You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 04:40:39