表达中间件测试摩卡柴

时间:2015-12-29 18:34:38

标签: node.js express mocha

有没有办法在Express中测试这种中间件:

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

我发现的唯一中间件测试是:

module.exports = function(request, response, next) {
    /*
     * Do something to REQUEST or RESPONSE
    **/

    if (!request.didSomething) {
        console.log("dsdsd");
        request.didSomething = true;
        next();
    } else {
        // Something went wrong, throw and error
        var error = new Error();
        error.message = 'Error doing what this does'
        next(error);        
    }
};


describe('Middleware test', function(){

    context('Valid arguments are passed', function() {
        beforeEach(function(done) {
            /* 
             * before each test, reset the REQUEST and RESPONSE variables 
             * to be send into the middle ware
            **/
            requests = httpMocks.createRequest({
                method: 'GET',
                url: '/css/main.css',
                query: {
                    myid: '312'
                }
            });
            responses = httpMocks.createResponse();

            done(); // call done so that the next test can run
        });

        it('does something', function(done) {
            /*
             * Middleware expects to be passed 3 arguments: request, response, and next.
             * We are going to be manually passing REQUEST and RESPONSE into the middleware
             * and create an function callback for next in which we run our tests
            **/
            middleware(responses, responses, function next(error) {
                /*
                 * Usually, we do not pass anything into next except for errors, so because
                 * in this test we are passing valid data in REQUEST we should not get an 
                 * error to be passed in.
                **/
                if (error) { throw new Error('Expected not to receive an error'); }

                // Other Tests Against request and response
                if (!responses.didSomething) { throw new Error('Expected something to be done'); }

                done(); // call done so we can run the next test
            }); // close middleware
        }); // close it
    }); // close context
}); // close describe

这与上面提供的简单中间件(就像测试回调的基本功能一样)很好用但是使用更复杂的中间件我无法使其工作。是否有可能测试这种中间件?

2 个答案:

答案 0 :(得分:20)

以下是使用chaisinon可以使用的简单设置:

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() {
    ...
  });

});

从那里,您可以为模式匹配等添加更精细的测试。由于您只使用req.url,因此您不必模拟整个Request对象(由Express)你可以使用一个url属性的简单对象。

答案 1 :(得分:1)

我用node-mocks-http对中间件进行了单元测试。这是我的代码:

function responseMiddleware(req, res, next) {    
    res.sendResponse = (...args) => { 
        //<==== Code removed from here
    };
    next();
}

在我的规格文件中,我这样做的是:

var expect = require('chai').expect;
var sinon  = require('sinon');    
var responseMiddleware = require('./response');
var httpMocks = require('node-mocks-http');


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

        responseMiddleware({}, {}, nextSpy);
        expect(nextSpy.calledOnce).to.be.true;
      });
      it('should add sendResponse key', function() {
        var nextSpy = sinon.spy();
        var req = httpMocks.createRequest();
        var res = httpMocks.createResponse();

        responseMiddleware(req, res, nextSpy);
        expect(nextSpy.calledOnce).to.be.true;
        responseMiddleware(req, res, () => {
            expect(res).to.have.property('sendResponse');        
        })        
      });
    });

如果您使用的是异步调用,则可以使用await,然后再调用done()。