Search code examples
javascriptnode.jsmocha.jschaichaining

Representing chained methods and members Typescript through Mocha tests


I am testing a node.js controller file using mocha and chai and i'm unable to mock out the response object in my test

TestController.ts

export class TestController {

    static async getTest(req:any, res:any, next:object) {
        console.log("Test");
        //some code here
        res.status(200).json(result.rows);
    }

and this works perfectly fine when I call the API, returns the right response etc. But when I try to test this Controller, here is what I have for my test file

Test.ts

it('Get Test method', async function () {
    let req = {params: {testid: 12345}};
    let res:any = {
      status: function() { }
    };

    res.json = '';
    let result = await TestController.getTest(req, res, Object);
});

I am not sure how to represent the response object here. If I just declare the variable res in the following way

let res:any;

I see the following error in my test

TypeError: Cannot read property 'json' of undefined

I am not sure how my response data structure res should be for making this test work.


Solution

  • You should use sinon.stub().returnsThis() to mock the this context, it allows you to call chain methods.

    E.g.

    controller.ts:

    export class TestController {
      static async getTest(req: any, res: any, next: object) {
        console.log('Test');
        const result = { rows: [] };
        res.status(200).json(result.rows);
      }
    }
    

    controller.test.ts:

    import { TestController } from './controller';
    import sinon from 'sinon';
    
    describe('61645232', () => {
      it('should pass', async () => {
        const req = { params: { testid: 12345 } };
        const res = {
          status: sinon.stub().returnsThis(),
          json: sinon.stub(),
        };
        const next = sinon.stub();
        await TestController.getTest(req, res, next);
        sinon.assert.calledWithExactly(res.status, 200);
        sinon.assert.calledWithExactly(res.json, []);
      });
    });
    

    unit test results with 100% coverage:

      61645232
    Test
        ✓ should pass
    
    
      1 passing (14ms)
    
    ---------------|---------|----------|---------|---------|-------------------
    File           | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
    ---------------|---------|----------|---------|---------|-------------------
    All files      |     100 |      100 |     100 |     100 |                   
     controller.ts |     100 |      100 |     100 |     100 |                   
    ---------------|---------|----------|---------|---------|-------------------