Search code examples
node.jsmockingjestjsintegration-testingsupertest

Mock function under router in Node js


Please consider the following scenario, but I could not solve it. A class are called under the router("/"). I would like to test router ("/") call and mock myFunc result.

class A {
  myFunc = async () => {
    await ...
    return result
  }
}

Controller file - C:

router.get("/", async (req, res) => {
    var a = new A();

    a.myFunc()
        .then(result => {
            res.json({"message": result});
        }).catch(e => {
            return []
    })
});

C.test.js:

const request = require("supertest");
const app = require("../C");

jest.mock('A');

test("Test route /", async done => {

        const myFuncMock = jest.fn().mockImplementation(() => [...]);
        A.prototype.myFunc = myFuncMock;

        await request(app)
            .get("/")
            .then(res => {
                expect(res.status).toBe(200); // Not asserted
            });
        done()

    });

I could not success to mock function results under the router.


Solution

  • Here is the integration test solution:

    app.js:

    const express = require('express');
    const { Router } = require('express');
    const A = require('./a');
    
    const app = express();
    const router = Router();
    
    router.get('/', async (req, res) => {
      const a = new A();
    
      a.myFunc()
        .then((result) => {
          res.json({ message: result });
        })
        .catch((e) => {
          return [];
        });
    });
    
    app.use(router);
    
    module.exports = app;
    

    a.js:

    class A {
      myFunc = async () => {
        const result = await 'real data';
        return result;
      };
    }
    
    module.exports = A;
    

    app.test.js:

    const app = require('./app');
    const request = require('supertest');
    const A = require('./a');
    
    jest.mock('./a', () => {
      const mA = { myFunc: jest.fn() };
      return jest.fn(() => mA);
    });
    
    describe('61505692', () => {
      afterEach(() => {
        jest.clearAllMocks();
      });
      it('should pass', () => {
        const mA = new A();
        mA.myFunc.mockResolvedValueOnce('fake result');
        return request(app)
          .get('/')
          .then((res) => {
            expect(res.status).toBe(200);
          });
      });
    });
    

    integration test results with coverage report:

     PASS  stackoverflow/61505692/app.test.js (11.834s)
      61505692
        ✓ should pass (34ms)
    
    ----------|---------|----------|---------|---------|-------------------
    File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
    ----------|---------|----------|---------|---------|-------------------
    All files |   92.31 |      100 |      75 |   91.67 |                   
     app.js   |   92.31 |      100 |      75 |   91.67 | 16                
    ----------|---------|----------|---------|---------|-------------------
    Test Suites: 1 passed, 1 total
    Tests:       1 passed, 1 total
    Snapshots:   0 total
    Time:        13.785s