node.js - 即使正在调用监视的函数,Sinon spy 也会失败
问题描述
我无法理解为什么 sinon 间谍对我来说失败了,即使我正在监视的函数确实在我的测试期间被调用(我通过一些简单的控制台日志记录证明了这一点)。
所以说我有如下内容:
index.js
let MyModule = require('./src/index.js');
MyModule = new MyModule();
module.exports = {
DoStuff: MyModule.DoStuff,
doOtherStuff: MyModule.doOtherStuff,
};
src/index.js
const MyModule = function MyModule() {
const self = this;
self.doOtherStuff = function doOtherStuff() {
console.log('doOtherStuff called!!!')
}
self.DoStuff = async function DoStuff() {
const xhr = self.axiosInstance();
await xhr.post()
.then((res) => {
self.doOtherStuff(res.data);
})
.catch((_err) => {
console.log(_err);
});
};
}
module.exports = MyModule;
我的测试如下:
const nock = require('nock');
const sinon = require('sinon');
const MyModule = require('../index.js');
describe('When calling DoStuff succeeds in making the xhr call', () => {
before(() => {
nock(apiHostName)
.post('/some-path')
.reply(200, { foo: 'bar' });
});
it('should call doOtherStuff', async () => {
const spy = sinon.spy(MyModule, 'doOtherStuff');
await MyModule.DoStuff();
sinon.assert.calledOnce(spy);
});
});
我在我的测试运行器输出中看到我的 doOtherStuff 函数输出中的控制台日志,但测试失败,说间谍被调用零次。
我想知道这是否归结为我正在测试的代码的异步性质,但我确保在我的测试中使用 async/await。我一定是在做一些愚蠢的事情,我哪里错了?
谢谢
更新
所以我尝试将功能剥离回更基本的东西,现在有以下内容:
const MyModule = function MyModule() {
const self = this;
self.doOtherStuff = function doOtherStuff() {
console.log('doOtherStuff called!!!')
}
self.DoStuff = function DoStuff() {
self.doOtherStuff();
};
}
module.exports = MyModule;
所以这将排除我可能遇到的任何异步/等待问题。
但即使在运行以下简单测试时,间谍也不会被调用:
const MyModule = require('../index.js');
it('should call doOtherStuff', () => {
const spy = sinon.spy(MyModule, 'doOtherStuff');
MyModule.DoStuff();
sinon.assert.calledOnce(spy);
});
但是,如果我监视console.log
它,它就会过去。我一定是误解了这里的一个非常基本的原理,但我不知道它是什么!
这与我module.exports
的声明方式有关吗?因此,即使我试图在我index.js
的 ( doOtherStuff: MyModule.doOtherStuff
) 中监视顶级导出,这不是在我的测试中调用 DoStuff 时在内部实际调用的内容?
解决方案
问题
包裹在 中spy
的属性不是被调用的属性。
细节
sinon.spy
接受一个对象和一个属性名称,并将该属性名称处的函数包装在一个间谍中。
在这种情况下,对象是index.js
.
模块导出是一个具有两个属性的对象,这些属性指向在 中MyModule
创建的内部实例上的方法index.js
。所以该doOtherStuff
对象的属性现在是 aspy
并且该DoStuff
属性仍然只是DoStuff
对内部MyModule
实例的属性的引用。
当测试然后调用MyModule.DoStuff()
它调用DoStuff
内部MyModule
实例的doOtherStuff
属性,该属性调用内部实例的属性,该属性MyModule
记录到控制台。
关键是doOtherStuff
内部MyModule
实例的属性被直接调用,而doOtherStuff
导出的对象的属性index.js
从未被调用。
然后导出的对象的spy
on属性正确断言它被调用了 0 次。doOtherStuff
index.js
解决方案
确保在spy
实际调用的属性上创建。
在这种情况下,最简单的方法是直接MyModule
从以下位置导出实例index.js
:
let MyModule = require('./src/index.js');
MyModule = new MyModule();
module.exports = MyModule;
现在,当spy
创建它时,它直接在doOtherStuff
内部MyModule
实例的属性上创建,并且会正确报告它被调用过一次。
推荐阅读
- python - 是否使用缩放的测试数据进行预测?
- javascript - 我如何编写此类组件以响应功能组件。?
- javascript - 为什么我在尝试获取数字总和时得到 NaN
- c# - 将图像绑定到 ToolTip WPF C#
- tensorflow - 将张量板添加到联合设置
- ag-grid - Ag-grid React:无限行模型的数据源中的预设过滤器
- jquery - Data-id 的值是父元素的值
- constraint-programming - 了解 Minizincs geost 约束的输入格式
- python - 设置中的调试导致媒体文件夹中的图像出现问题
- java - 有没有办法通过媒体商店访问特定于应用程序的外部存储文件夹?