我正在与Sinon一起使用Mocha,并尝试测试递归调用(fibonacci)。我的代码是:
'use strict';
let sinon = require('sinon'),
chai = require('chai'),
expect = chai.expect;
chai.use(require('sinon-chai'));
let fib = function (n) {
if (n === 0) {
return 0;
} else if (n === 1) {
return 1;
} else {
return fib(n-2) + fib(n-1);
}
};
describe('fib', function() {
it('should repeat calculations', function() {
let originalFib = fib;
fib = sinon.spy(fib)
expect(fib(6)).to.equal(8);
expect(fib).to.have.callCount(25);
fib = originalFib;
});
});
此代码按原样工作,但是,如果我替换以下行:
let fib = function (n) {
具有:
const fib = function (n) {
我收到以下错误:
TypeError:分配给常量变量。
这符合预期,但提出了一个问题,我将如何测试使用Sinon声明为const的递归函数?
编辑 Jasmine有一个名为.callThrough()的东西,它似乎允许测试递归函数。
在我看来,没有办法与Sinon重复这种行为吗?我查看了以下错误报告/功能请求:
https://github.com/sinonjs/sinon/issues/668
https://github.com/sinonjs/sinon/issues/989
谢谢。
答案 0 :(得分:2)
直接在函数上调用sinon.spy
会在原始函数周围创建一个包装器,该包装器可跟踪调用和返回的值,但不会对其进行修改,因此您无需记住它并恢复它。
有了这些信息,显而易见的答案就是简单地给你的间谍起个别的名字:
describe('fib', function() {
it('should repeat calculations', function() {
const spy = sinon.spy(fib);
expect(spy(6)).to.equal(8);
expect(spy).to.have.callCount(25);
});
});
这种方法对非递归函数很好用,但是您可能会注意到,虽然第一个断言通过了,但是第二个失败了,只进行了一次间谍调用。
问题在于,这里还有另外一个问题。函数fib直接调用自身,并且通过用sinon.spy
包装该函数不会跟踪那些直接的递归调用。
the answer here中提供了有关此问题的更多详细信息以及相应的解决方案。
答案 1 :(得分:0)
将代码更改为const fib = function(n)
时的主要问题是因为您拥有此后续代码fib = sinon.spy(fib)
。我们无法使用const
重新声明任何变量的赋值。
对于这种测试,根据我的经验,我觉得没有必要使用spy
,除非您有其他函数可以在fib
内调用。我们可以执行并检查所有可能情况的值。
'use strict';
const sinon = require('sinon'),
chai = require('chai'),
expect = chai.expect;
chai.use(require('sinon-chai'));
const fib = function (n) {
if (n === 0) {
return 0;
} else if (n === 1) {
return 1;
} else {
return fib(n - 2) + fib(n - 1);
}
};
describe('fib', function () {
it('should repeat calculations', function () {
expect(fib(0)).to.equal(0); // add more cases
expect(fib(1)).to.equal(1);
expect(fib(6)).to.equal(8);
});
});
希望有帮助。