在我的TDD之旅中,我正在使用Mocha,chai和sinon。 那里肯定有学习曲线。
我的目标是编写一个测试来验证method4是否已执行。我如何实现这一目标?
// MyData.js
class MyData {
constructor(input) {
this._runMethod4 = input; //true or false
this.underProcessing = this.init();
}
method1() { return this.method2() }
method2() {
if (this._runMethod4) {
return this.method4();
} else {
return this.method3();
}
method4(){
return thirdPartyAPI.getData();
}
method3(){
return someAPI.fetchData();
}
init(){
return this.method1();
}
}
MyData.spec.js
describe('MyData', () => {
it('should execute method 4', function() {
let foo = new MyData(true);
foo.underProcessing.then(()=>{
// How do I verify that method4 was executed ??
expect(foo.method4.callCount).to.equal(1);
});
});
})
答案 0 :(得分:3)
以下是一个例子:
const expect = require('chai').expect;
const sinon = require('sinon');
const sinonTest = require('sinon-test');
sinon.test = sinonTest.configureTest(sinon);
sinon.testCase = sinonTest.configureTestCase(sinon);
describe("MyData", () => {
it("should execute method 4", sinon.test(function() {
let spy = this.spy(MyData.prototype, 'method4');
let foo = new MyData(true);
return foo.underProcessing.then(() => {
expect(spy.callCount).to.equal(1);
});
}));
});
作为附加要求,我添加了sinon-test
,因为在测试运行后帮助清理间谍/存根非常有用。
主要特色是这一行:
let spy = this.spy(MyData.prototype, 'method4');
这将取代MyData.prototype.method4
一个Sinon间谍,它是一个传递函数(因此它调用原始函数),它将记录它的调用方式,频率,参数等等。你需要在创建实例之前执行此操作,因为否则您太晚了(该方法可能已经通过构造函数中以this.init()
开头的方法调用链调用。)
如果你想使用存根而不是传递(因此它不会调用原始方法),你也可以这样做:
let spy = this.stub(MyData.prototype, 'method4').returns(Promise.resolve('yay'));
因此,thirdPartyAPI.getData()
不会调用method4
并返回其结果,而是会返回使用值yay
解析的承诺。
其余的代码应该说明一切,但有一点需要注意:在return
前面有一个明确的foo.underProcessing.then(...)
。
我认为foo.underProcessing
是一个承诺,所以它是异步的,这意味着你的测试也应该是异步的。由于Mocha支持承诺,当你从测试中返回一个承诺时,Mocha将知道如何正确处理它(这是另一种使用Mocha制作asynchronous test的方法,涉及回调函数,但是当你和#39;重新测试基于承诺的代码,您不应该使用这些代码,因为它很容易遇到超时或吞噬异常。)