Search code examples
javascriptmocha.jssinonsupertestsinon-chai

Sinon Spy not called but original function is called


My spy is not being called, even though I can see the console log in the original function getting called

Mocha test:

const { expect } = require('chai');
const supertest = require('supertest');
const MyController = require('../../Controllers/MyController');
const sandbox = require('sinon').createSandbox();
const app = require('../../app');

describe('GET /endpoint', () => {
    it('calls handler', (done) => {
        const mySpy = sandbox.spy(MyController, 'handler');

        supertest(app)
            .get('/endpoint')
            .expect(() => {
                expect(mySpy.called).to.be.true;
            })
            .end(done);
    });
});

Express controller:

function handler(request, response) {
    console.log('I can see this method being called');
    return response.sendStatus(200);
}

module.exports = {
    handler
};

Express router:

const router = require('express').Router();
const MyController = require('../Controllers/MyController');

router
    .get('/endpoint', MyController.handler);

module.exports = router;

Any ideas please?


Solution

  • In these lines of code:

    router
        .get('/endpoint', MyController.handler)
    

    ...you're passing the actual function defined on MyController.handler. What router.get() got was simply a reference to that function.
    When you later, in the test, wrap MyController.handler in a spy, that doesn't change the fact that router.get() has a separate reference to the original function.

    What you need to do is to make sure that the route handler always invokes MyController.handler(). Change the expression into this:

    router
        .get('/endpoint', () => MyController.handler())