Search code examples
node.jstypescriptmocha.jssinon

How to mock a controller?


How to mock this I don't know. Can someone help me on this ?

I want to write the test case for this controller. But I am new to this so where to start and how to write the test case I don't understand.

import { Route } from '../common/ExpressWrapper';
import {partnerDao} from '../factory/AppFactory';
import { keysToLowerCase } from '../util/TpsUtil';
import ErrorResponse from '../models/common/ErrorResponse'

const constants = require('../constants');
const logger = require('../logger/index.ts')('controller/PartnerController');

const GetPartnerByPKController: Route = (req, res) => {
    logger.debug("Entering GetPartnerByPKController()");
    let uuid = req.params.uuid;
    console.time("TimeTaken:DBCall:");
    console.log("Entering GetPartnerByPKController()"+uuid);
    partnerDao.getPartnerByUuid(uuid).then(result => {
        if (result != undefined) {
            res.status(200).send(result);
        } else {
            logger.info("Partner for the uuid:" + uuid + " was not found");
            res.status(404).send(new ErrorResponse("Partner not found", "404.1.100", constants.ERROR_LINK + "404.1.100", []));
        }
    }).catch(error => {
        console.log("Error in accessing GetPartnerByPK API", JSON.stringify(error))
        logger.error("Error in accessing GetPartnerByPK API", JSON.stringify(error));
        res.status(500).send(new ErrorResponse("Internal Server Error", "500.1.103", constants.ERROR_LINK + "500.1.103", [JSON.stringify(error.message)]));
    });
    console.timeEnd("TimeTaken:DBCall:");
    logger.debug("Leaving GetPartnerByPKController()");
}

Solution

  • Here is the unit test solution:

    controller.ts:

    import { partnerDao } from "./AppFactory";
    import ErrorResponse from "./ErrorResponse";
    
    type Route = any;
    
    const constants = {
      ERROR_LINK: "ERROR_LINK",
    };
    
    export const GetPartnerByPKController: Route = async (req, res) => {
      console.debug("Entering GetPartnerByPKController()");
      let uuid = req.params.uuid;
      console.time("TimeTaken:DBCall:");
      console.log("Entering GetPartnerByPKController()" + uuid);
      await partnerDao
        .getPartnerByUuid(uuid)
        .then((result) => {
          if (result != undefined) {
            res.status(200).send(result);
          } else {
            console.info("Partner for the uuid:" + uuid + " was not found");
            res
              .status(404)
              .send(new ErrorResponse("Partner not found", "404.1.100", constants.ERROR_LINK + "404.1.100", []));
          }
        })
        .catch((error) => {
          console.log("Error in accessing GetPartnerByPK API", JSON.stringify(error));
          console.error("Error in accessing GetPartnerByPK API", JSON.stringify(error));
          res
            .status(500)
            .send(
              new ErrorResponse("Internal Server Error", "500.1.103", constants.ERROR_LINK + "500.1.103", [
                JSON.stringify(error.message),
              ]),
            );
        });
      console.timeEnd("TimeTaken:DBCall:");
      console.debug("Leaving GetPartnerByPKController()");
    };
    

    AppFactory.ts:

    export const partnerDao = {
      async getPartnerByUuid(id) {
        return "real data";
      },
    };
    

    ErrorResponse.ts:

    export default class ErrorResponse {
      public desc = "";
      public args: any;
      public code: string = "";
      public message: string = "";
      constructor(message, code, desc, args) {
        this.message = message;
        this.desc = desc;
        this.args = args;
        this.code = code;
      }
    }
    

    controller.test.ts:

    import { GetPartnerByPKController } from "./controller";
    import { partnerDao } from "./AppFactory";
    import sinon from "sinon";
    import { expect } from "chai";
    import ErrorResponse from "./ErrorResponse";
    
    describe("GetPartnerByPKController", () => {
      afterEach(() => {
        sinon.restore();
      });
      it("should get parter by uuid correctly", async () => {
        const mResponse = "fake data";
        const getPartnerByUuidStub = sinon.stub(partnerDao, "getPartnerByUuid").resolves(mResponse);
        const mReq = { params: { uuid: "123" } };
        const mRes = { status: sinon.stub().returnsThis(), send: sinon.stub() };
        await GetPartnerByPKController(mReq, mRes);
        sinon.assert.calledWith(mRes.status, 200);
        sinon.assert.calledWith(mRes.status().send, mResponse);
        sinon.assert.calledWith(getPartnerByUuidStub, "123");
      });
    
      it("should 404", async () => {
        const mResponse = undefined;
        const getPartnerByUuidStub = sinon.stub(partnerDao, "getPartnerByUuid").resolves(mResponse);
        const mReq = { params: { uuid: "123" } };
        const mRes = { status: sinon.stub().returnsThis(), send: sinon.stub() };
        await GetPartnerByPKController(mReq, mRes);
        sinon.assert.calledWith(mRes.status, 404);
        sinon.assert.calledWith(
          mRes.status().send,
          new ErrorResponse("Partner not found", "404.1.100", "ERROR_LINK" + "404.1.100", []),
        );
        sinon.assert.calledWith(getPartnerByUuidStub, "123");
      });
    
      it("should 500", async () => {
        const mError = new Error("unknown error");
        const getPartnerByUuidStub = sinon.stub(partnerDao, "getPartnerByUuid").rejects(mError);
        const mReq = { params: { uuid: "123" } };
        const mRes = { status: sinon.stub().returnsThis(), send: sinon.stub() };
        await GetPartnerByPKController(mReq, mRes);
        sinon.assert.calledWith(mRes.status, 500);
        sinon.assert.calledWith(
          mRes.status().send,
          new ErrorResponse("Internal Server Error", "500.1.103", "ERROR_LINK" + "500.1.103", [
            JSON.stringify(mError.message),
          ]),
        );
        sinon.assert.calledWith(getPartnerByUuidStub, "123");
      });
    });
    

    Unit test result with coverage report:

      GetPartnerByPKController
    Entering GetPartnerByPKController()
    Entering GetPartnerByPKController()123
    TimeTaken:DBCall:: 21.633ms
    Leaving GetPartnerByPKController()
        ✓ should get parter by uuid correctly
    Entering GetPartnerByPKController()
    Entering GetPartnerByPKController()123
    Partner for the uuid:123 was not found
    TimeTaken:DBCall:: 0.532ms
    Leaving GetPartnerByPKController()
        ✓ should 404
    Entering GetPartnerByPKController()
    Entering GetPartnerByPKController()123
    Error in accessing GetPartnerByPK API {}
    Error in accessing GetPartnerByPK API {}
    TimeTaken:DBCall:: 35.619ms
    Leaving GetPartnerByPKController()
        ✓ should 500 (38ms)
    
    
      3 passing (124ms)
    
    --------------------|----------|----------|----------|----------|-------------------|
    File                |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
    --------------------|----------|----------|----------|----------|-------------------|
    All files           |    98.51 |      100 |    91.67 |    98.41 |                   |
     AppFactory.ts      |       50 |      100 |        0 |       50 |                 3 |
     ErrorResponse.ts   |      100 |      100 |      100 |      100 |                   |
     controller.test.ts |      100 |      100 |      100 |      100 |                   |
     controller.ts      |      100 |      100 |      100 |      100 |                   |
    --------------------|----------|----------|----------|----------|-------------------|
    

    Source code: https://github.com/mrdulin/mocha-chai-sinon-codelab/tree/master/src/stackoverflow/59319054