0

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

也许一双新的眼睛可以帮助我理解为什么我的方法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')
    })
  })
})
4

2 回答 2

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

于 2019-11-21T08:12:10.443 回答
0

看来proxyquire您的操作./lib/convert不正确。convert使用objectToPopulateTemplate和回调调用Original 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')
})
于 2017-11-17T20:00:58.997 回答