Search code examples
node.jsmocha.jstddchaisinon

How to test class called or not using mocha & chai with sinon TDD?


I want to test class called or not in nodejs, mocha & chai with sinon. I tried with stub but not worked as what I expected.

someMiddleware.js

module.export.someMiddleware = async(req,res,next)=>{
const responseData = await someReturnFunction(req);

if (!responseData || responseData == null) { 
      throw new SomeExtendedErrrorClass("stringArg");
    }
res.send(responseData);
}

testFile.js

sinon
      .stub(someMiddleWare , "someReturnFunction")
      .returns(null);
    const stubClass = sinon.stub(SomeExtendedErrrorClass, "constructor");
    someMiddleware(req, res, next);
    expect(stubClass).to.have.be.called;

Even the SomeExtendedErrrorClass called, sinon not detected.


Solution

  • Sinon does not support stub standalone function or class imported from other modules. You need to use Link Seams, we will be using proxyquire to construct our seams.

    E.g.

    someMiddleware.js:

    const someReturnFunction = require('./someReturnFunction');
    const SomeExtendedErrrorClass = require('./SomeExtendedErrrorClass');
    
    module.exports.someMiddleware = async (req, res, next) => {
      const responseData = await someReturnFunction(req);
    
      if (!responseData || responseData == null) {
        throw new SomeExtendedErrrorClass('stringArg');
      }
      res.send(responseData);
    };
    

    SomeExtendedErrrorClass.js:

    class SomeExtendedErrrorClass extends Error {}
    

    someReturnFunction.js:

    async function someReturnFunction() {
      return 'real implementation';
    }
    

    someMiddleware.test.js:

    const chai = require('chai');
    const chaiAsPromised = require('chai-as-promised');
    const proxyquire = require('proxyquire');
    const sinon = require('sinon');
    const SomeExtendedErrrorClass = require('./SomeExtendedErrrorClass');
    
    chai.use(chaiAsPromised);
    const { expect } = chai;
    
    describe('68640048', () => {
      it('should get and send response data', async () => {
        const someReturnFunctionStub = sinon.stub().resolves('teresa teng');
    
        const { someMiddleware } = proxyquire('./someMiddleware', {
          './someReturnFunction': someReturnFunctionStub,
        });
        const mReq = {};
        const mRes = { send: sinon.stub() };
        await someMiddleware(mReq, mRes);
        sinon.assert.calledWithExactly(mRes.send, 'teresa teng');
      });
    
      it('should throw error', async () => {
        const someReturnFunctionStub = sinon.stub().resolves(null);
        const { someMiddleware } = proxyquire('./someMiddleware', {
          './someReturnFunction': someReturnFunctionStub,
        });
    
        const mReq = {};
        const mRes = { send: sinon.stub() };
        await expect(someMiddleware(mReq, mRes)).to.eventually.rejectedWith(SomeExtendedErrrorClass);
      });
    });
    

    test result:

      68640048
        ✓ should get and send response data
        ✓ should throw error
    
    
      2 passing (10ms)