gpt4 book ai didi

javascript - 全局 Jest SpyOn 函数不调用原始函数

转载 作者:行者123 更新时间:2023-12-05 00:33:07 26 4
gpt4 key购买 nike

我希望有人可以帮助我理解 js 原型(prototype)和 jest.spOn() 的交互性.
我有一个小例子:
文件 TestObj.ts 中的示例类:

export default class TestObj {
foo() {
// Do Something e.g.
console.log("Hello World!");
}
}
以下示例测试用例成功,但 console.log永远不会被执行。
import TestObj from './TestObj';

const spyObj = jest.spyOn(TestObj.prototype, 'foo');
test('debug test', () => {
const obj = new TestObj();
obj.foo();
expect(spyObj).toHaveBeenCalled();
});
如果我将示例测试用例更改为以下内容,则测试成功并且 console.log语句按预期调用。
import TestObj from './TestObj';

test('debug test', () => {
const spyObj = jest.spyOn(TestObj.prototype, 'foo');
const obj = new TestObj();
obj.foo();
expect(spyObj).toHaveBeenCalled();
});
知道为什么使用全局 spyOn 变量的版本不能按预期工作吗?

编辑:
它似乎与原型(prototype)无关。
没有任何类的函数也存在同样的问题,
将第一个代码片段 ( TestObj.ts) 编辑为:
export foo() {
// Do Something e.g.
console.log("Hello World!");
};
对于更新的第二个片段,我们收到了相同的问题。 (测试成功,但从未到达控制台日志。)
import * as testlib from './TestObj';

const spyObj = jest.spyOn(testlib, 'foo');
test('debug test', () => {
testlib.foo();
expect(spyObj).toHaveBeenCalled();
});
但是,如果我们将第二个代码段更新为以下代码,则测试成功并执行控制台日志:
import * as testlib from './TestObj';

const spyObj: jest.SpyInstance;

beforeEach(() => {
spyObj = jest.spyOn(testlib, 'foo');
});
test('debug test', () => {
testlib.foo();
expect(spyObj).toHaveBeenCalled();
});
但是我仍然不知道为什么我会发现这个问题。

最佳答案

谁遇到过这个帖子,
问题说明
我做了很多研究(try&error、mdn、jest manpage 和很多媒体文章),我想我找到了奇怪行为的原因。要理解这个问题,了解以下几点很重要:

  • 1:JS原型(prototype)是全局变量,对应类型的每个对象都依赖。
  • 2:Jest 不会在每次测试后重置全局变量,之前或在任何测试中对全局变量所做的更改将保留在整个测试套件(文件)中。
  • 3:jest spy on 函数实际上是指定函数的模型,其实现调用了它自己的函数。例如。:jest.SpyOn(TestObj.prototype, 'foo');实际实现为:TestObj.prototype.foo = new jest.fn().mockImplementation(()=>{original_TestObj.prototype.foo()});这意味着监视类原型(prototype)的函数实际上是在更改全局变量。
  • 4:根据您的 Jest 配置,可以在每次测试之前将模型功能重置为默认值。但要注意 spyOn 的默认函数似乎与 jest.fn() 相同它自己,一个空的实现,这意味着模型仍然可以调用但没有代码,尤其是没有执行原始实现。

  • 解决方案
  • 如果您希望测试用例彼此独立,请避免更改全局变量。
  • 避免在测试用例中监视原型(prototype),如果您仅在单个测试中需要 spy ,请尝试监视本地对象,例如:

  • test('should foo', () => {
    const testObj = new TestObj();
    const spyOnFn = jest.spyOn(testObj, 'foo');

    // Do anything

    expect(spyOnFn).to//Have been anything
    });
  • 如果需要 spyOn相同功能的实现
    在多个测试中尝试为测试创建一个全局变量
    但是使用 jest 的每个功能之前设置 spy 。这个
    功能在所有模拟重置后执行(如果启用)。
    例如:

  • let spyOnFunction1: jest.SpyInstance;

    beforeEach(()=> {
    spyOnFunction1 = jest.spyOn(TestObj.prototype, 'foo');
    });

    关于javascript - 全局 Jest SpyOn 函数不调用原始函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69078319/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com