sinonhapi

Why is this basic sinon stub not working in my hapi web application


I'm just starting to look into adding some automated unit testing into my hapi web application and I'm using lab and sinon to do this. For some reason though I can't get the first test of sinon to stub a function call that is made in a get handler. Here is the get handler:

const { mytest } = require('../services/my-service')

module.exports = [
  
  {
    method: 'GET',
    path: `${urlPrefix}/healthcheck-detailed`,
    config: {
      auth: false
    },
    handler: async (request, h) => {

      mytest()
      
      return h.response('Success').code(200);
    }
  }]

the my-service that the function being called looks like this


function mytest(){
  console.log("My test called")
}
module.exports = { mytest }

and the test looks like this

const Lab = require('@hapi/lab');
const Code = require('@hapi/code');
const { expect } = Code;
const { it, describe, before, after, beforeEach, afterEach } = exports.lab = Lab.script();
const { init } = require('../../../server/')
const sinon = require('sinon')

describe('Healthcheck /get', () => {
    let server
    let mytestStub

    beforeEach(async () => {
        server = await init()

        // Stub the mytest function directly using the full module path
        mytestStub = sinon.stub(require('../../../server/services/my-service'), 'mytest').callsFake(() => {
            console.log("Stubbed mytest called");
        });
    })

    afterEach(async () => {
        await server.stop()

        // Restore the original mytest function
        mytestStub.restore();
    })

    it('calls the correct functions on /healthcheck-detailed', { timeout: 30000 }, async () => {
        const response = await server.inject({
            method: 'GET',
            url: '/healthcheck-detailed'
        })

        console.log("Stub called: ", mytestStub.called);

        expect(mytestStub.calledOnce).to.be.true();
    })
});

When I run this I would expect the test to pass and the console output should show "Stubbed mytest called" but instead it fails and shows "My test called". What am I missing? Why does the stub get ignored?


Solution

  • @fosbie don't destructure the stubbed method under test when importing it. It should be explicitly imported.

    const myService = require('../services/my-service')
    
    module.exports = [
      
      {
        method: 'GET',
        path: `${urlPrefix}/healthcheck-detailed`,
        config: {
          auth: false
        },
        handler: async (request, h) => {
    
          myService.mytest()
          
          return h.response('Success').code(200);
        }
      }]
    

    See the explanation here