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

Jest单元测试遇双重问题:window.open未实现+函数调用断言失败

React Jest测试失败:NavigateToOtherSite未被调用且window.open报错

问题概述

编写React组件及Jest单元测试后,出现两个问题:

  • 断言显示NavigateToOtherSite函数调用次数为0,不符合预期
  • 控制台抛出Error: Not implemented: window.open错误

相关代码如下:

const NavigateToOtherSite = (url: string) => {
  window.open(url, 'blank');
};
export default NavigateToOtherSite;

App.tsx

import * as React from 'react';
import './style.css';
import NavigateToOtherSite from './Navigate';

export default function App() {
  return (
    <div data-test='id-1' onClick={() => NavigateToOtherSite('https://fast.com/')}>
      <h1>Hello StackBlitz!</h1>
      <p>Start editing to see some magic happen :)</p>
    </div>
  );
}

App.test.tsx

import React from 'react';
import { shallow } from 'enzyme';
import * as Navigate from './Navigate';

it('should open correct website', async () => {
    let test = jest
      .spyOn(Navigate, 'NavigateToOtherSite')
      .mockImplementation();
    const wrapper = shallow(<App/>);
    wrapper.find('[data-test="id-1"]').simulate('click');
    expect(test).toHaveBeenCalled();
  });

失败详情

expect(jest.fn()).toHaveBeenCalled()

Expected number of calls: >= 1
Received number of calls: 0

控制台错误:

console.error
Error: Not implemented: window.open

解决方案

1. 修复NavigateToOtherSite未被调用的问题

核心原因是导入方式与Spy匹配不兼容:

  • 组件中使用默认导入import NavigateToOtherSite from './Navigate'
  • 测试中试图Spy命名导出NavigateToOtherSite,但原文件仅导出默认函数,导致Spy未生效

方案一:修改测试的Spy逻辑

直接针对模块的default属性进行Spy:

import React from 'react';
import { shallow } from 'enzyme';
import App from './App';

it('should open correct website', () => {
    // Spy默认导出的函数
    const navigateSpy = jest.spyOn(require('./Navigate'), 'default')
      .mockImplementation(() => {});
    const wrapper = shallow(<App/>);
    wrapper.find('[data-test="id-1"]').simulate('click');
    
    // 验证调用次数与参数
    expect(navigateSpy).toHaveBeenCalledTimes(1);
    expect(navigateSpy).toHaveBeenCalledWith('https://fast.com/');
    
    // 清理Spy
    navigateSpy.mockRestore();
  });

方案二:改用命名导出

调整Navigate.ts为命名导出:

export const NavigateToOtherSite = (url: string) => {
  window.open(url, 'blank');
};

组件中同步修改导入方式:

import { NavigateToOtherSite } from './Navigate';

此时原测试中的Spy代码即可正常工作。

2. 解决window.open未实现错误

Jest的jsdom环境默认未实现window.open,可通过两种方式处理:

  • 在测试中提前Mock该方法:
    beforeAll(() => {
      window.open = jest.fn();
    });
    
    afterAll(() => {
      delete window.open;
    });
    
  • 或者通过mockImplementation替换原函数逻辑(如方案一的测试代码,已跳过原函数的window.open调用)

最终完整测试示例

import React from 'react';
import { shallow } from 'enzyme';
import App from './App';

beforeAll(() => {
  window.open = jest.fn();
});

afterAll(() => {
  delete window.open;
});

it('should open correct website', () => {
    const navigateSpy = jest.spyOn(require('./Navigate'), 'default')
      .mockImplementation(() => {});
    const wrapper = shallow(<App/>);
    wrapper.find('[data-test="id-1"]').simulate('click');
    
    expect(navigateSpy).toHaveBeenCalledTimes(1);
    expect(navigateSpy).toHaveBeenCalledWith('https://fast.com/');
    
    navigateSpy.mockRestore();
  });

内容的提问来源于stack exchange,提问作者90CK

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 19:23:10