我正在尝试测试一个在其中调用request.get()
函数的函数。
我正在尝试的是覆盖回调函数的所有分支。我试图在不将回调函数分离到不同函数的情况下实现它,因为它使用了上部闭包的变量。
这是一个例子来说明.. foo.js:
var request = require('request');
function func(arg1, arg2) {
request.get({...}, function(error, response, body) {
// do stuff with arg1 and arg2 // want to be covered
if (...) { // want to be covered
... // want to be covered
} else if (...) { // want to be covered
... // want to be covered
} else {
... // want to be covered
}
});
}
exports.func = func;
我试图用sinon和proxyquire来存根。
foo.spec.js(与sinon衔接):
var foo = require('./foo'),
var sinon = require('sinon'),
var request = require('request');
var requestStub = sinon.stub(request, 'get', function(options, callback) {
callback(new Error('Custom error'), {statusCode: 400}, 'body');
}); // Trying to replace it with a function that calls the callback immediately so not to deal with async operations in test
foo.func(5, 3);
foo.spec.js(带有proxyquire的存根):
var requestStub = {};
var proxyquire = require('proxyquire'),
var foo = proxyquire('./foo', {'request': requestStub}),
var sinon = require('sinon');
requestStub.get = function(options, callback) {
callback(new Error('Custom error'), {statusCode: 400}, 'body');
}; // Trying to replace it with a function that calls the callback immediately so not to deal with async operations in test
foo.func(5, 3);
两者都没有奏效。当我尝试调试时,我从未点击回调函数,这表明我没有正确地存储request.get()
方法,使其仍然是异步操作。
我很感激有人告诉我在两种情况下我做错了什么(sinon& proxyquire)以及如何修复它的例子。
答案 0 :(得分:0)
这是使用sinon
和mocha
的单元测试解决方案:
index.js
:
var request = require("request");
function func(arg1, arg2) {
request.get("https://github.com/mrdulin", function(error, response, body) {
console.log(arg1, arg2);
if (error) {
console.log(error);
} else if (response.status === 200) {
console.log(response);
} else {
console.log("others");
}
});
}
exports.func = func;
index.spec.js
:
var foo = require("./");
var sinon = require("sinon");
var request = require("request");
describe("func", () => {
afterEach(() => {
sinon.restore();
});
it("should handle error", () => {
const logSpy = sinon.spy(console, "log");
const getStub = sinon.stub(request, "get");
foo.func(1, 2);
const mError = new Error("network error");
getStub.yield(mError, null, null);
sinon.assert.calledWith(
getStub,
"https://github.com/mrdulin",
sinon.match.func
);
sinon.assert.calledWith(logSpy.firstCall, 1, 2);
sinon.assert.calledWith(logSpy.secondCall, mError);
});
it("should handle response", () => {
const logSpy = sinon.spy(console, "log");
const getStub = sinon.stub(request, "get");
foo.func(1, 2);
const mResponse = { status: 200 };
getStub.yield(null, mResponse, null);
sinon.assert.calledWith(
getStub,
"https://github.com/mrdulin",
sinon.match.func
);
sinon.assert.calledWith(logSpy.firstCall, 1, 2);
sinon.assert.calledWith(logSpy.secondCall, mResponse);
});
it("should handle other situation", () => {
const logSpy = sinon.spy(console, "log");
const getStub = sinon.stub(request, "get");
foo.func(1, 2);
const mResponse = { status: 500 };
getStub.yield(null, mResponse, null);
sinon.assert.calledWith(
getStub,
"https://github.com/mrdulin",
sinon.match.func
);
sinon.assert.calledWith(logSpy.firstCall, 1, 2);
sinon.assert.calledWith(logSpy.secondCall, "others");
});
});
覆盖率100%的单元测试结果:
func
1 2
Error: network error
at Context.it (/Users/ldu020/workspace/github.com/mrdulin/mocha-chai-sinon-codelab/src/stackoverflow/37764363/index.spec.js:1:4103)
at callFn (/Users/ldu020/workspace/github.com/mrdulin/mocha-chai-sinon-codelab/node_modules/mocha/lib/runnable.js:387:21)
at Test.Runnable.run (/Users/ldu020/workspace/github.com/mrdulin/mocha-chai-sinon-codelab/node_modules/mocha/lib/runnable.js:379:7)
at Runner.runTest (/Users/ldu020/workspace/github.com/mrdulin/mocha-chai-sinon-codelab/node_modules/mocha/lib/runner.js:535:10)
at /Users/ldu020/workspace/github.com/mrdulin/mocha-chai-sinon-codelab/node_modules/mocha/lib/runner.js:653:12
at next (/Users/ldu020/workspace/github.com/mrdulin/mocha-chai-sinon-codelab/node_modules/mocha/lib/runner.js:447:14)
at /Users/ldu020/workspace/github.com/mrdulin/mocha-chai-sinon-codelab/node_modules/mocha/lib/runner.js:457:7
at next (/Users/ldu020/workspace/github.com/mrdulin/mocha-chai-sinon-codelab/node_modules/mocha/lib/runner.js:362:14)
at Immediate._onImmediate (/Users/ldu020/workspace/github.com/mrdulin/mocha-chai-sinon-codelab/node_modules/mocha/lib/runner.js:425:5)
at runCallback (timers.js:705:18)
at tryOnImmediate (timers.js:676:5)
at processImmediate (timers.js:658:5)
✓ should handle error (48ms)
1 2
{ status: 200 }
✓ should handle response
1 2
others
✓ should handle other situation
3 passing (58ms)
---------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
---------------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
index.js | 100 | 100 | 100 | 100 | |
index.spec.js | 100 | 100 | 100 | 100 | |
---------------|----------|----------|----------|----------|-------------------|
源代码:https://github.com/mrdulin/mocha-chai-sinon-codelab/tree/master/src/stackoverflow/37764363