如何 sinon spy 模块导出实用函数
How to sinon spy module export utility functions
在 javascript (ES6) 中,我有一个只包含一些函数的实用程序模块,然后在文件末尾,我像这样导出它们:
module.exports = {
someFunction1,
someFunction2,
someFunction3,
}
然后我想为那些函数编写单元测试。一些功能相互依赖;它们以某种方式相互调用,例如,someFunction1 可能会调用 someFunction2。没有循环问题。
一切正常,直到我需要监视其中一个函数被调用。我该怎么做?目前我正在使用 Chai 和 Sinon。
在测试文件中,我将整个文件作为一个模块导入:
const wholeModule = require('path/to/the/js/file')
最后,我的测试如下所示:
it('should call the someFunction2', (done) => {
const spy = sinon.spy(wholeModule, 'someFunction2')
wholeModule.someFunction1() // someFunction2 is called inside someFunction1
assert(spy.calledOnce, 'someFunction2 should be called once')
done()
})
问题是,测试失败,因为在someFunction1中,直接使用了someFunction2函数。我将间谍应用到模块对象的函数中。但那是不同的对象。这是 someFunction1 的示例:
function someFunction1() {
someFunction2()
return 2;
}
我知道它不起作用的原因,但我不知道在这种情况下让它起作用的最佳做法是什么?请帮忙!
您可以使用 rewire 模块。这是一个例子:
源代码:
function someFunction1() {
console.log('someFunction1 called')
someFunction2();
}
function someFunction2() {
console.log('someFunction2 called')
}
module.exports = {
someFunction1: someFunction1,
someFunction2: someFunction2
}
测试用例:
'use strict';
var expect = require('chai').expect;
var rewire = require('rewire');
var sinon = require('sinon');
var funcs = rewire('../lib/someFunctions');
it('should call the someFunction2', () => {
var someFunction2Stub = sinon.stub();
funcs.__set__({
someFunction2: someFunction2Stub,
});
someFunction2Stub.returns(null);
funcs.someFunction1();
expect(someFunction2Stub.calledOnce).to.equal(true);
});
如您所知,发生这种情况是因为您存根的是导出的引用,而不是模块中的实际方法。它适用于任何包含您要替换的模块的模块,因为它们包含导出的引用,但在同一模块内时,它只是调用本地函数。
我找到的最简单的解决方案就是调用参考:
function someFunction1() {
this.someFunction2()
return 2;
}
在 javascript (ES6) 中,我有一个只包含一些函数的实用程序模块,然后在文件末尾,我像这样导出它们:
module.exports = {
someFunction1,
someFunction2,
someFunction3,
}
然后我想为那些函数编写单元测试。一些功能相互依赖;它们以某种方式相互调用,例如,someFunction1 可能会调用 someFunction2。没有循环问题。
一切正常,直到我需要监视其中一个函数被调用。我该怎么做?目前我正在使用 Chai 和 Sinon。
在测试文件中,我将整个文件作为一个模块导入:
const wholeModule = require('path/to/the/js/file')
最后,我的测试如下所示:
it('should call the someFunction2', (done) => {
const spy = sinon.spy(wholeModule, 'someFunction2')
wholeModule.someFunction1() // someFunction2 is called inside someFunction1
assert(spy.calledOnce, 'someFunction2 should be called once')
done()
})
问题是,测试失败,因为在someFunction1中,直接使用了someFunction2函数。我将间谍应用到模块对象的函数中。但那是不同的对象。这是 someFunction1 的示例:
function someFunction1() {
someFunction2()
return 2;
}
我知道它不起作用的原因,但我不知道在这种情况下让它起作用的最佳做法是什么?请帮忙!
您可以使用 rewire 模块。这是一个例子:
源代码:
function someFunction1() {
console.log('someFunction1 called')
someFunction2();
}
function someFunction2() {
console.log('someFunction2 called')
}
module.exports = {
someFunction1: someFunction1,
someFunction2: someFunction2
}
测试用例:
'use strict';
var expect = require('chai').expect;
var rewire = require('rewire');
var sinon = require('sinon');
var funcs = rewire('../lib/someFunctions');
it('should call the someFunction2', () => {
var someFunction2Stub = sinon.stub();
funcs.__set__({
someFunction2: someFunction2Stub,
});
someFunction2Stub.returns(null);
funcs.someFunction1();
expect(someFunction2Stub.calledOnce).to.equal(true);
});
如您所知,发生这种情况是因为您存根的是导出的引用,而不是模块中的实际方法。它适用于任何包含您要替换的模块的模块,因为它们包含导出的引用,但在同一模块内时,它只是调用本地函数。
我找到的最简单的解决方案就是调用参考:
function someFunction1() {
this.someFunction2()
return 2;
}