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()おり、まだ非同期操作になっています。両方のシナリオ(シノンとプロキシクワイア)で何が間違っていたのか、それを修正する方法の例を教えていただければ幸いです。

4

1 に答える 1

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

于 2019-11-20T14:00:13.093 に答える