Search code examples
javascriptnode.jsunit-testingsinon

Auth middleware not calling stub - NodeJS, sinon


Similar questions have been asked before & I have looked at & followed them but no luck:

  1. Sinon stub being skipped as node express middleware
  2. node express es6 sinon stubbing middleware not working
  3. How to mock middleware in Express to skip authentication for unit test?

The general answer I get from these is that the module (app.js in my case) should be required AFTER the auth middleware method has been stubbed. I have done this, but still calls the original middleware:

src/app.js

const authentication = require('./authentication')

...

app.use(['/api/users', '/api/groups'], authentication.ensureAuthenticed])

module.exports = app

src/authentication.js

const { isValidAuth } = require('./lib')

exports.ensureAuthenticated = (req, res, next) => {
    ...
}

__helpers__/supertest.js

// This file just calls endpoints with supertest but this is the only file
// that includes 'app'
const app = require('../../src/app')

module.exports = {
    post: {
        ...
    },
    get: {
        ...
    },
    put: {
        ...
    },
    delete: {
        ...
    }
}

users.spec.js

const authentication = require('../../src/authentication')
const authenticationStubs = require('../__stubs__/authentication')

let supertest
let ensureAuthStub

describe('Users', () => {
    before(() => {
        ensureAuthStub = sinon.stub(authentication, 'ensureAuthenticated').callsFake(authenticationStubs.ensureAuthenticated)
        supertest = require('../__helpers__/supertest')
    })

    // tests

    after(() => {
        ensureAuthStub.restore()
    })
})

__stubs__/authentication.js

exports.ensureAuthenticated = (req, res, next) => {
    ...
}

In users.spec.js, I load in supertest.js (which loads in src/app.js) AFTER the method has been mocked so I am not sure why the original is still being invoked.

I have also attempted to manually clear the cache before mocking but still does not work.


Solution

  • Turns out it was something to do with having supertest.js require app.js. I now have users.spec.js require the app and pass it it into supertest methods as a param. It now works. Still unsure why though