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

Node环境下Jasmine无法创建函数Spy的问题求助

问题根源与解决方案

核心问题拆解

你遇到的问题有两个关键原因:

  1. 内部函数引用不匹配:init 调用的是模块内本地定义的 clone 变量,而非导出的 client.clone 引用——就算你替换了导出的 clone,init 依然会调用原始函数,spy 根本不会被触发。
  2. ES模块属性限制:import * as client 得到的命名空间对象,其属性默认是 configurable: false,而 Jasmine 的 spyOn 需要修改属性描述符来实现拦截逻辑,这直接导致 spyOn 无法正常创建 spy。

解决方案一:用普通对象封装导出函数(最贴近Angular使用方式)

重构模块结构,把函数放到普通对象里导出,这样对象属性默认是可配置的,spyOn 能正常工作,同时确保 init 调用对象内的 clone:

修改后的 index.js:

let state = null;

const templates = { obj: { a:1, b:2} };

export const client = {
    clone: (obj) => JSON.parse(JSON.stringify(obj)),
    init: () => state = client.clone(templates.obj)
};

修改后的 index.spec.js:

import { client } from '../../index.js';

describe("test", () => {
    it("should spy on the clone method", () => {
        spyOn(client, 'clone').and.callThrough();
        client.init();
        expect(client.clone).toHaveBeenCalled();
    });
})

解决方案二:手动替换导出的clone为spy(无需大改模块结构)

先调整模块内的引用关系,让 init 指向导出的 clone 绑定,再手动创建spy替换导出的函数:

修改后的 index.js:

let state = null;

const templates = { obj: { a:1, b:2} };

// 先导出clone,让init引用这个实时绑定
export const clone = (obj) => JSON.parse(JSON.stringify(obj));
export const init = () => state = clone(templates.obj);

修改后的 index.spec.js:

import * as client from '../../index.js';

describe("test", () => {
    it("should spy on the clone method", () => {
        // 保存原始函数,测试后恢复避免影响其他用例
        const originalClone = client.clone;
        // 创建包含原始逻辑的spy
        const cloneSpy = jasmine.createSpy('clone').and.callFake(originalClone);
        
        // 利用writable: true的特性替换导出的clone
        client.clone = cloneSpy;
        
        client.init();
        expect(cloneSpy).toHaveBeenCalled();
        
        // 恢复原始函数
        client.clone = originalClone;
    });
})

内容的提问来源于stack exchange,提问作者Dirk Deshommes

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 05:55:16