在 sinon 中使用异步回调存根方法
stubbing method with async callback in sinon
我有一个调用 extractText()
的 parsePDF()
方法,returns 它会导致异步回调。
问题
我如何编写测试 只测试 parsePDF
调用 extractText
一次,以及传递给任何 path
参数parsePDF
? (我对 extractText
和 cleanUp
进行了单独的单元测试。)
下面是parsePDF
方法的基本结构:
Parser.parsePDF(path, callback) {
Parser.extractText(path, function gotResult(err, raw_text) {
if (err) {
callback(err)
return;
}
var clean_text = Parser.cleanUp(raw_text)
callback(null, clean_text);
});
};
我试过的
尽管阅读了 Sinon documentation on callsArg, Mocha/Chai/Sinon tutorials, various SO posts such as this one about stubbing function with callback - causing test method to timeout,但我仍然没有理解编写正确测试需要什么。
此尝试失败并显示消息
Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test.
有道理,没有触发回调
it('should call extractText() with path argument', function(done) {
sandbox.stub(Parser, 'extractText')
Parser.parsePDF('a known path', function(err, bill) {
expect(sinon).calledOnce(Parser.extractText).calledWith('a known path')
done()
});
});
但以下 yeilds()
也失败,消息 undefined is not a function
指向 expect...
行:
it('should call extractText() with path argument', function(done) {
sandbox.stub(UtilityBillParser, 'extractText').yields(null, 'some text')
Parser.parsePDF('a known path', function(err, bill) {
expect(sinon).calledOnce(Parser.extractText).calledWith('a known path')
done()
});
});
与 .callsArg(1)
一样:
it('should call extractText() with path argument', function(done) {
sandbox.stub(UtilityBillParser, 'extractText').callsArg(1)
UtilityBillParser.parsePDF('a known path', function(err, bill) {
expect(sinon).calledOnce(UtilityBillParser.extractText).calledWith('a known path')
done()
});
});
由于您完全取消了 extractText() 方法,因此永远不会调用其回调,因此需要 none 与回调相关的特殊处理。以下作品:
it('should call extractText() with path argument', function() {
sandbox.stub(Parser, 'extractText')
Parser.parsePDF('a known path', 'ignored');
sinon.assert.calledOnce(Parser.extractText)
sinon.assert.calledWith(Parser.extractText, 'a known path', sinon.match.func)
});
在第二个断言中使用 sinon.match.func
反映了 parsePDF
创建自己的匿名函数以传递给 extractText
的事实;您能做的最好的事情就是断言 some 函数已传递给 extractText
.
单元测试解决方案如下:
parser.js
:
const Parser = {
parsePDF(path, callback) {
Parser.extractText(path, function gotResult(err, raw_text) {
if (err) {
callback(err);
return;
}
var clean_text = Parser.cleanUp(raw_text);
callback(null, clean_text);
});
},
extractText(path, callback) {
callback();
},
cleanUp(rawText) {
return "real clean text";
},
};
module.exports = Parser;
parser.test.js
:
const Parser = require("./parser");
const sinon = require("sinon");
describe("Parser", () => {
afterEach(() => {
sinon.restore();
});
describe("#parsePDF", () => {
it("should clean up raw test", () => {
const callback = sinon.stub();
sinon.stub(Parser, "extractText").yields(null, "fake raw text");
sinon.stub(Parser, "cleanUp").returns("fake clean text");
Parser.parsePDF("./somepath", callback);
sinon.assert.calledWith(Parser.extractText, "./somepath", sinon.match.func);
sinon.assert.calledWith(Parser.cleanUp, "fake raw text");
sinon.assert.calledWith(callback, null, "fake clean text");
});
it("should handle err", () => {
const callback = sinon.stub();
const mError = new Error("some error");
sinon.stub(Parser, "extractText").yields(mError, null);
sinon.stub(Parser, "cleanUp").returns("fake clean text");
Parser.parsePDF("./somepath", callback);
sinon.assert.calledWith(Parser.extractText, "./somepath", sinon.match.func);
sinon.assert.calledWith(callback, mError);
});
});
});
带有覆盖率报告的单元测试结果:
Parser
#parsePDF
✓ should clean up raw test
✓ should handle err
2 passing (9ms)
----------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
----------------|----------|----------|----------|----------|-------------------|
All files | 93.75 | 100 | 77.78 | 93.75 | |
parser.js | 80 | 100 | 50 | 80 | 13,16 |
parser.test.js | 100 | 100 | 100 | 100 | |
----------------|----------|----------|----------|----------|-------------------|
源代码:https://github.com/mrdulin/mocha-chai-sinon-codelab/tree/master/src/Whosebug/30163720
我有一个调用 extractText()
的 parsePDF()
方法,returns 它会导致异步回调。
问题
我如何编写测试 只测试 parsePDF
调用 extractText
一次,以及传递给任何 path
参数parsePDF
? (我对 extractText
和 cleanUp
进行了单独的单元测试。)
下面是parsePDF
方法的基本结构:
Parser.parsePDF(path, callback) {
Parser.extractText(path, function gotResult(err, raw_text) {
if (err) {
callback(err)
return;
}
var clean_text = Parser.cleanUp(raw_text)
callback(null, clean_text);
});
};
我试过的
尽管阅读了 Sinon documentation on callsArg, Mocha/Chai/Sinon tutorials, various SO posts such as this one about stubbing function with callback - causing test method to timeout,但我仍然没有理解编写正确测试需要什么。
此尝试失败并显示消息
Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test.
有道理,没有触发回调
it('should call extractText() with path argument', function(done) {
sandbox.stub(Parser, 'extractText')
Parser.parsePDF('a known path', function(err, bill) {
expect(sinon).calledOnce(Parser.extractText).calledWith('a known path')
done()
});
});
但以下 yeilds()
也失败,消息 undefined is not a function
指向 expect...
行:
it('should call extractText() with path argument', function(done) {
sandbox.stub(UtilityBillParser, 'extractText').yields(null, 'some text')
Parser.parsePDF('a known path', function(err, bill) {
expect(sinon).calledOnce(Parser.extractText).calledWith('a known path')
done()
});
});
与 .callsArg(1)
一样:
it('should call extractText() with path argument', function(done) {
sandbox.stub(UtilityBillParser, 'extractText').callsArg(1)
UtilityBillParser.parsePDF('a known path', function(err, bill) {
expect(sinon).calledOnce(UtilityBillParser.extractText).calledWith('a known path')
done()
});
});
由于您完全取消了 extractText() 方法,因此永远不会调用其回调,因此需要 none 与回调相关的特殊处理。以下作品:
it('should call extractText() with path argument', function() {
sandbox.stub(Parser, 'extractText')
Parser.parsePDF('a known path', 'ignored');
sinon.assert.calledOnce(Parser.extractText)
sinon.assert.calledWith(Parser.extractText, 'a known path', sinon.match.func)
});
在第二个断言中使用 sinon.match.func
反映了 parsePDF
创建自己的匿名函数以传递给 extractText
的事实;您能做的最好的事情就是断言 some 函数已传递给 extractText
.
单元测试解决方案如下:
parser.js
:
const Parser = {
parsePDF(path, callback) {
Parser.extractText(path, function gotResult(err, raw_text) {
if (err) {
callback(err);
return;
}
var clean_text = Parser.cleanUp(raw_text);
callback(null, clean_text);
});
},
extractText(path, callback) {
callback();
},
cleanUp(rawText) {
return "real clean text";
},
};
module.exports = Parser;
parser.test.js
:
const Parser = require("./parser");
const sinon = require("sinon");
describe("Parser", () => {
afterEach(() => {
sinon.restore();
});
describe("#parsePDF", () => {
it("should clean up raw test", () => {
const callback = sinon.stub();
sinon.stub(Parser, "extractText").yields(null, "fake raw text");
sinon.stub(Parser, "cleanUp").returns("fake clean text");
Parser.parsePDF("./somepath", callback);
sinon.assert.calledWith(Parser.extractText, "./somepath", sinon.match.func);
sinon.assert.calledWith(Parser.cleanUp, "fake raw text");
sinon.assert.calledWith(callback, null, "fake clean text");
});
it("should handle err", () => {
const callback = sinon.stub();
const mError = new Error("some error");
sinon.stub(Parser, "extractText").yields(mError, null);
sinon.stub(Parser, "cleanUp").returns("fake clean text");
Parser.parsePDF("./somepath", callback);
sinon.assert.calledWith(Parser.extractText, "./somepath", sinon.match.func);
sinon.assert.calledWith(callback, mError);
});
});
});
带有覆盖率报告的单元测试结果:
Parser
#parsePDF
✓ should clean up raw test
✓ should handle err
2 passing (9ms)
----------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
----------------|----------|----------|----------|----------|-------------------|
All files | 93.75 | 100 | 77.78 | 93.75 | |
parser.js | 80 | 100 | 50 | 80 | 13,16 |
parser.test.js | 100 | 100 | 100 | 100 | |
----------------|----------|----------|----------|----------|-------------------|
源代码:https://github.com/mrdulin/mocha-chai-sinon-codelab/tree/master/src/Whosebug/30163720