nodejs - 没有调用sinon存根

时间:2017-11-17 14:29:48

标签: node.js mocha sinon proxyquire

由于某种原因,我在使用类似的设置正确运行这个简单的测试时遇到了一些麻烦,我之前曾多次使用过。

也许一双新鲜的眼睛可以帮助我理解为什么我的方法generateReport没有被调用而我的stubs没有被预期的参数触发?

记录了

BYEGOOD并且测试返回错误:AssertError: expected stub to be called with arguments

我的索引文件:

const errorHandler = require('./lib/handlers/error-handler')
const transformRequest = require('./lib/handlers/request-converter')
const convert = require('./lib/convert')

exports.generateReport = function generateReport(req, res) {
  console.log('HELLO')
  const objectToPopulateTemplate = transformRequest(req.body)
  convert(objectToPopulateTemplate, function (e, data) {
    if (e) {
      console.log('BYE')
      const error = errorHandler(e)
      return res.send(error.httpCode).json(error)
    }
    console.log('GOOD')
    res
      .set('Content-Type', 'application/pdf')
      .set('Content-Disposition', `attachment; filename=velocity_report_${new Date()}.pdf`)
      .set('Content-Length', data.length)
      .status(200)
      .end(data)
  })
}

我的测试文件:

const proxyquire = require('proxyquire')
const assert = require('assert')
const sinon = require('sinon')
const fakeData = require('./data/sample-request.json')


describe('report-exporter', () => {
  describe('generateReport', () => {
    const fakeError = new Error('Undefined is not a function')

    let res, resSendStub, resStatusStub, resEndStub, resSetStub, resJsonStub, req, convertStub, generate
    before(() => {
      resSendStub = sinon.stub()
      resJsonStub = sinon.stub()
      resStatusStub = sinon.stub()
      resEndStub = sinon.stub()
      resSetStub = sinon.stub()
      convertStub = sinon.stub()

      res = {
        send: function(errorCode) {
          return resSendStub(errorCode)
        },
        json: function(object) {
          return resJsonStub(object)
        },
        set: function(arg1, arg2) {
          return resSetStub(arg1, arg2)
        },
        status: function(code) {
          return resStatusStub(code)
        },
        end: function(data) {
          return resEndStub(data)
        }
      }
      req = {
        body: {}
      }

      generate = proxyquire('./../index', {
        './lib/convert': function() {
          return convertStub
        }
      })
    })


    it('Should return an error response', () => {
      convertStub.throws(fakeError)
      generate.generateReport(req, res)
      sinon.assert.calledWith(resSendStub, '500')
    })
  })
})

2 个答案:

答案 0 :(得分:0)

看起来您proxyquire错误地./lib/convertconvert。使用objectToPopulateTemplate和回调function (e, data)调用原始convert。这就是负责错误处理和发送响应的回调。

存根convertStub函数根本不关心提供的回调,因此回调永远不会被调用。

您最想要的是将参数传递给'./lib/convert': function(objectToPopulateTemplate, cb) { return convertStub(objectToPopulateTemplate, cb); } 并稍后处理它们:

it('Should return an error response', () => {
  generate.generateReport(req, res);
  const cb = convertStub.getCall(0).args[1];

  // simulate `convert` to fail
  cb(fakeError);

  sinon.assert.calledWith(resSendStub, '500')
})

然后

UIDatePicker

答案 1 :(得分:0)

这是单元测试解决方案:

index.js

const errorHandler = require("./error-handler");
const transformRequest = require("./request-converter");
const convert = require("./convert");

exports.generateReport = function generateReport(req, res) {
  console.log("HELLO");
  const objectToPopulateTemplate = transformRequest(req.body);
  convert(objectToPopulateTemplate, function(e, data) {
    if (e) {
      console.log("BYE");
      const error = errorHandler(e);
      return res.send(error.httpCode).json(error);
    }
    console.log("GOOD");
    res
      .set("Content-Type", "application/pdf")
      .set(
        "Content-Disposition",
        `attachment; filename=velocity_report_${new Date()}.pdf`
      )
      .set("Content-Length", data.length)
      .status(200)
      .end(data);
  });
};

error-handler.js

module.exports = function(error) {
  return error;
};

request-converter.js

module.exports = function transformRequest(body) {
  return body;
};

convert.js

module.exports = function convert(body, callback) {
  callback();
};

index.spec.js

const sinon = require("sinon");
const proxyquire = require("proxyquire");

describe("report-exporter", () => {
  describe("generateReport", () => {
    afterEach(() => {
      sinon.restore();
    });
    const fakeError = new Error("Undefined is not a function");
    fakeError.httpCode = 500;

    it("Should return an error response", () => {
      const logSpy = sinon.spy(console, "log");
      const mReq = { body: {} };
      const mRes = { send: sinon.stub().returnsThis(), json: sinon.stub() };
      const convertStub = sinon.stub();
      const errorHandlerStub = sinon.stub().returns(fakeError);
      const transformRequestStub = sinon.stub().returns(mReq.body);
      const generate = proxyquire("./", {
        "./convert": convertStub,
        "./error-handler": errorHandlerStub,
        "./request-converter": transformRequestStub
      });

      generate.generateReport(mReq, mRes);
      convertStub.yield(fakeError, null);
      sinon.assert.calledWith(transformRequestStub);
      sinon.assert.calledWith(convertStub, {}, sinon.match.func);
      sinon.assert.calledWith(errorHandlerStub, fakeError);
      sinon.assert.calledWith(logSpy.firstCall, "HELLO");
      sinon.assert.calledWith(logSpy.secondCall, "BYE");
    });
  });
});

带有覆盖率报告的单元测试结果:

  report-exporter
    generateReport
HELLO
BYE
      ✓ Should return an error response (94ms)


  1 passing (98ms)

----------------------|----------|----------|----------|----------|-------------------|
File                  |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------------------|----------|----------|----------|----------|-------------------|
All files             |     87.5 |       50 |     62.5 |     87.5 |                   |
 convert.js           |       50 |      100 |        0 |       50 |                 2 |
 error-handler.js     |       50 |      100 |        0 |       50 |                 2 |
 index.js             |    84.62 |       50 |      100 |    84.62 |             14,15 |
 index.spec.js        |      100 |      100 |      100 |      100 |                   |
 request-converter.js |       50 |      100 |        0 |       50 |                 2 |
----------------------|----------|----------|----------|----------|-------------------|

源代码:https://github.com/mrdulin/mocha-chai-sinon-codelab/tree/master/src/stackoverflow/47352972