【问题标题】:Correct way to unit test Express Middleware [duplicate]单元测试 Express 中间件的正确方法 [重复]
【发布时间】:2017-05-28 22:03:53
【问题描述】:

我有一个 Express 中间件,它被设置为在所有到达我的服务器的 POST 请求中检查有效的 Content-Type 标头,该中间件的代码如下:

import * as STRINGS from "../Common/strings";

function ContentTypeValidator(req, res, next) {
    let contentHeader = req.get("content-type");
    if(!contentHeader) {
        res.status(400).send(STRINGS.ERROR_CONTENT_TYPE_MISSING);
    } else {
        if(contentHeader.toLowerCase() !== "application/json") {
            res.status(415).send(STRINGS.ERROR_CONTENT_TYPE_UNSUPPORTED);
        } else {
            next();
        }
    }
}

export default ContentTypeValidator;

我正在为我的 TDD 使用 mochachainode-mocks-http,当 next() 不会被称为 res.send() 将为我处理此请求的结束时,我的问题围绕着测试。

it("Should return 200 for valid Content-Type header", (done) => {
    req = nodeMocks.createRequest({
        headers: {
            "Content-Type": "application/json"
        }
    });
    ContentTypeValidator(req, res, (err) => {
        res.statusCode.should.equal(200);
        expect(err).to.be.undefined;
        done();
    });
});

it("Should return 400 if Content-Type header is missing", (done) => {
    ContentTypeValidator(req, res, () => {});
    res.statusCode.should.equal(400);
    res._getData().should.equal("Content-Type header missing");
    done();
});

在上面的第一个测试中,我希望它通过,所以我传入一个函数来充当next() 函数,这个测试通过了。在第二个测试中,我希望这会失败,所以如果我传入一个函数,那么 mocah 会抱怨测试已经超过 2000 毫秒,因为回调函数从未被调用,这是可以预料的,因为 res.send() 在这种情况下正在处理它.

当涉及到像这样的 Express 中间件单元测试时,我编写第二个测试的方式是否正确,或者是否有更好/更可取的方式来做到这一点?

编辑:所以为了澄清,我专注于在不调用下一个回调时测试中间件,我显然重复的问题是查看使用sinon 来检查是否调用了下一个。我正在研究如何在不调用回调函数时进行单元测试。

【问题讨论】:

  • 我已经编辑了这个问题,以显示它与我显然复制的问题有何不同。
  • 可以用sinon来窥探res函数吗?例如var res = {statusCode: sinon.spy()}; 然后试试(res.statusCode).should.equal(500)

标签: node.js unit-testing express mocha.js chai


【解决方案1】:

看看这个答案

https://stackoverflow.com/a/34517121/4996928

var expect = require('chai').expect;
var sinon  = require('sinon');

var middleware = function logMatchingUrls(pattern) {
    return function (req, res, next) {
        if (pattern.test(req.url)) {
            console.log('request url', req.url);
            req.didSomething = true;
        }
        next();
    }
}

describe('my middleware', function() {

  describe('request handler creation', function() {
    var mw;

    beforeEach(function() {
      mw = middleware(/./);
    });

    it('should return a function()', function() {
      expect(mw).to.be.a.Function;
    });

    it('should accept three arguments', function() {
      expect(mw.length).to.equal(3);
    });
  });

  describe('request handler calling', function() {
    it('should call next() once', function() {
      var mw      = middleware(/./);
      var nextSpy = sinon.spy();

      mw({}, {}, nextSpy);
      expect(nextSpy.calledOnce).to.be.true;
    });
  });

  describe('pattern testing', function() {
    ...
  });

});

【讨论】:

  • 我实际上见过那个,但这个答案似乎更侧重于使用 sinon 来检查 next() 是否被实际调用。在我的例子中,我无法调用 next,因为响应在调用之前将被拒绝。
猜你喜欢
  • 1970-01-01
  • 2016-03-25
  • 1970-01-01
  • 2022-01-14
  • 2015-07-24
  • 1970-01-01
  • 2017-10-20
  • 2011-06-20
  • 1970-01-01
相关资源
最近更新 更多