Search code examples
node.jsexpressmocha.jschaisinon

how to mock configurable middleware in node js with sinon and mocha


I have configurable middleware where I can pass parameters and based on that it calls next function.

middleware code:

File: my-middleware.js

exports.authUser = function (options) {
  return function (req, res, next) {
    // Implement the middleware function based on the options object
    next()
  }
}

var mw = require('./my-middleware.js')

app.use(mw.authUser({ option1: '1', option2: '2' }))

How to mock the middleware using sinon js?

I have done in this way but, it throwing me "TypeError: next is not a function".

Here is my unit test code:

  it("Should return data by id", (done: any) => {

        sandbox.stub(mw, 'authUser')
            .callsFake((req: any, res: any, next: any) => { return next(); });

        server = require('../../index');

        let req = {
            "id": '123'
        }

        chai.request(server)
            .post("/user")
            .send(req)
            .end((request, res) => {

                expect(res.status).to.equal(200);
                expect(res.body.success).to.equal(true);

                done();
            });
    });

Can you help me to mock the configurable middleware? Thanks in advance!!


Solution

  • The authUser is a high order function, so you need to stub it for this.

    E.g.

    mws.js:

    exports.authUser = function(options) {
      return function(req, res, next) {
        // Implement the middleware function based on the options object
        next();
      };
    };
    

    app.js:

    const express = require('express');
    const mws = require('./mws');
    const app = express();
    
    app.use(mws.authUser({ option1: '1', option2: '2' }));
    
    app.post('/user', (req, res, next) => {
      res.json({ success: true });
    });
    
    module.exports = app;
    

    app.integration.test.js:

    const chai = require('chai');
    const chaiHttp = require('chai-http');
    const sandbox = require('sinon').createSandbox();
    const mws = require('./mws');
    
    chai.use(chaiHttp);
    const expect = chai.expect;
    
    describe('61818474', () => {
      afterEach(() => {
        sandbox.restore();
      });
      it('Should return data by id', (done) => {
        sandbox.stub(mws, 'authUser').callsFake((options) => (req, res, next) => {
          return next();
        });
        const server = require('./app');
        const req = { id: '123' };
        chai
          .request(server)
          .post('/user')
          .send(req)
          .end((request, res) => {
            expect(res.status).to.equal(200);
            expect(res.body.success).to.equal(true);
            sandbox.assert.calledWith(mws.authUser, { option1: '1', option2: '2' });
            done();
          });
      });
    });
    

    integration test results with coverage report:

      61818474
        ✓ Should return data by id (257ms)
    
    
      1 passing (265ms)
    
    ----------|---------|----------|---------|---------|-------------------
    File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
    ----------|---------|----------|---------|---------|-------------------
    All files |      80 |      100 |   33.33 |      80 |                   
     app.js   |     100 |      100 |     100 |     100 |                   
     mws.js   |   33.33 |      100 |       0 |   33.33 | 2-4               
    ----------|---------|----------|---------|---------|-------------------