即使在测试期间确实调用了我所监视的功能(我通过一些简单的控制台日志记录就证明了这一点),我仍然无法理解为什么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进行调用时,这实际上不是内部调用吗?
答案 0 :(得分:2)
spy
中包装的属性不是被调用的属性。
sinon.spy
接受一个对象和一个属性名称,并将该功能包装在间谍中。
在这种情况下,对象是index.js
的模块导出。
模块导出是一个具有两个属性的对象,这些属性指向在MyModule
中创建的内部index.js
实例上的方法。因此,该对象的doOtherStuff
属性现在是spy
,而DoStuff
属性仍然只是对内部DoStuff
实例的MyModule
属性的引用。
当测试然后调用MyModule.DoStuff()
时,它将调用内部DoStuff
实例的MyModule
属性,该属性调用内部doOtherStuff
实例的MyModule
属性记录到控制台。
关键是内部doOtherStuff
实例的MyModule
属性被直接调用,而doOtherStuff
导出的对象的index.js
属性从未被调用。 / p>
spy
导出的对象的doOtherStuff
属性上的index.js
然后正确地断言它被调用了0次。
确保在实际调用的属性上创建spy
。
在这种情况下,最简单的方法是直接从MyModule
导出index.js
实例:
let MyModule = require('./src/index.js');
MyModule = new MyModule();
module.exports = MyModule;
现在,创建spy
时,它是直接在内部doOtherStuff
实例的MyModule
属性上创建的,并且会正确地报告它被调用过一次。