0

我正在尝试测试一个在其中调用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)以及如何解决它的示例。

4

1 回答 1

0

sinon这是一个使用and的单元测试解决方案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

于 2019-11-20T14:00:13.093 回答