How to mock Express response object in Node tests using Mocha

Issue

I need to test a function that requires the response as argument, I’m using mocha and sequelize in node environment with express framework. My code is scaffolded in multiple files, but I need to test only the superactivator istance. These are my files:

route.js

const express = require('express');
const router = express.Router();

const rcv_pcController = require('../controllers/rcv_pc.controller');

router.post('/', rcv_pcController.switchMode);

module.exports = router;

rcv_pc.controller.js

const superActivator = require('../helpers/superactivator');
...

const switchMode = async (req, res) => {
    ...

    switch (tipo) {
        case "1":
            {
                if (modo == "1") {
                    superActivator.checkLicense(license, hwId, oem, expire, nowDate, ip, allowedSerials, res)
                }
                else if (modo == "2") {
                    superActivator.generateLicense(license, hwId, reqCode, nowDate, ip, res);
                }
                else if (modo == "3") {
                    superActivator.registerLicense(license, hwId, reqCode, nowDate, customerName, referenteName, referentePhone, ip, res)
                }
                break;
            }
    }
}

module.exports.switchMode = switchMode;

superactivator.js

const pcRepo = require("../repositories/pc.server.repository");
const repository = require('../repositories/rcvpc.server.repository');
...

class SuperActivator {

    ...
    checkLicense(license, hwId, oem, expDate, nowDate, ip, allowedSerials, res) {
        repository.findLicense(license).then(key => {
            // console.log(key[0]);
            if (key[0]) {
                if (!isset(key[0]['SS_ALLOWED_SERIALS']) || is_null(key[0]['SS_ALLOWED_SERIALS'])) {
                    key[0]['SS_ALLOWED_SERIALS'] = "";
                }
                if (this.updatePcRx(hwId, ip, nowDate) == 0) {
                    return res.send(this.licCheckResult.server_error);
                }
                if (this.checksetBanned(hwId) == 0) {
                    return res.send(this.licCheckResult.hwid_banned);
                }
                if (!isset(key[0]['SP_HW_ID'])) {
                    return res.send(this.licCheckResult.key_virgin);
                }
                if (key[0]['SS_STATUS'] < 1) {
                    return res.send(this.licCheckResult.key_unallowed);
                }
                if (key[0]['SP_HW_ID'] != hwId) {
                    if (this.setKeyMismatched(key[0]['SS_ID']) == 1) {
                        return res.send(this.licCheckResult.key_moved);
                    }
                }
                if ((strtotime(key[0]['SS_EXPIRE']) < strtotime(expDate))
                    || (strtotime(nowDate) < strtotime(key[0]['SP_PC_DATE_TIME']))
                    || (strtotime(nowDate) < time() - 60 * 60 * 24 * 2)) {
                    if (this.setKeyMismatched(key[0]['SS_ID']) == 1) {
                        return res.send(this.licCheckResult.dates_hacked);
                    } else {
                        return res.send(this.licCheckResult.server_error);
                    }
                }
                if ((key[0]['SS_OEM'] != oem)
                    || (strtotime(key[0]['SS_EXPIRE']) > strtotime(expDate) || strcmp(key[0]['SS_ALLOWED_SERIALS'], this.decodeToMortal(allowedSerials)) != 0)) {
                    return res.send(this.licCheckResult.key_info_to_update);
                }
                if (strtotime(key[0]['SS_EXPIRE']) <= strtotime(nowDate)) {
                    return res.send(this.licCheckResult.key_expired);
                }
                return res.send(this.licCheckResult.key_ok);
            } else {
                return res.send(this.licCheckResult.key_insesistente);
            }
        }).catch(err => res.send(err.errors));
    }

    generateLicense(license, hwId, reqCode, nowDate, ip, res) {
        pcRepo.updatePcRx(hwId, ip, nowDate);

        repository.findOem(license, hwId)
            .then((foundOem) => {
                if (foundOem[0]) {
                    const keyCode = this.generateValidKey(this.decodeToMortal(reqCode));
                    let patchKey = keyCode;
                    if (keyCode.length != 10 || this.checkValidKey(keyCode, patchKey) == 'KO') {
                        return res.send(this.licCheckResult.invalid_reqcode);
                    } else {
                        let oem = '';
                        switch (foundOem[0]['SS_OEM']) {
                            case 0:
                                oem = 'thisisnotoem'
                                break;
                            case 1:
                                oem = 'thisisoem'
                                break;
                            case 2:
                                oem = 'thisisoemdoc'
                                break;
                            case 3:
                                oem = 'thisislock'
                                break;
                            case 10:
                                oem = 'thisisnotoem_lecu'
                                break;
                            case 11:
                                oem = 'thisisdemo_lecu'
                                break;
                            case 12:
                                oem = 'thisisoem_lecu'
                                break;
                        }
                        
                        const keepDate = str_replace('-', "", foundOem[0]['SS_EXPIRE'])
                        const allowedSerials = this.getAllowedSerials(foundOem[0]['SS_ID'])
                        console.log(allowedSerials);
                        const key =
                            this.codeToGod(keyCode) + '|'
                            + this.codeToGod(patchKey) + '|'
                            + this.codeToGod(oem) + '|'
                            + this.codeToGod(keepDate) + '|'
                            + this.codeToGod(allowedSerials);
                        // console.log(key);
                        return res.send(key);
                    }
                } else {
                    return res.send(this.licCheckResult.key_insesistente);
                }
            }).catch(err => res.send(err.errors));
    }

    registerLicense(license, hwId, reqKey, pcDate, customerName, referenteName, referentePhone, ip, res) {
        pcRepo.findOne(hwId)
            .then((pc) => {
                let pcId = '';
                if (!pc) {
                    const data = {
                        SP_HW_ID: hwId,
                        SP_LAST_RX: Date.now(),
                        SP_IP: ip,
                        SP_PC_DATE_TIME: new Date().toISOString().slice(0, 10)
                    }
                    pcRepo.create(data)
                        .then((newPc) => {
                            if (!newPc) {
                                return res.send(this.licCheckResult.server_error);
                            }
                            return pcId = newPc['SP_ID']
                        }).catch(err => res.send(err.errors));
                } else {
                    pcId = pc['SP_ID']
                }
                console.log(pcId);
                if (isset(pcId) || pcId.length == 0 || pcId == 0) {
                    return res.send(this.licCheckResult.server_error);
                }
                repository.updateLicense(pcId, customerName, referenteName, referentePhone, license)
                    .spread((results, metadata) => {
                        if (!results) {
                            return res.send(this.licCheckResult.server_error);
                        }
                        return this.generateLicense(license, hwId, reqKey, pcDate, ip, res);
                    }).catch(err => res.send(err.errors))
            }).catch(err => res.send(err.errors));
    }

}

...

const superActivator = new SuperActivator(licCheckResult);

module.exports = superActivator;

For the sake of clarity I omit all the Superactivator class methods. This is my test code:

superactivator.spec.js

...

const superactivator = require('../helpers/superactivator');

...

describe('checkLicense()', function () {
    it('sks ', async function () {
        // here I mock the request.body data
        const ip = '127.0.0.1';
        const license = "A2YyLM8i3G7feJt7Hlm8hxlYk";
        const hwId = "123490EN40";
        const oem = 12;
        const expDate = "2019-10-10";
        const nowDate = null; // "2018-09-05"
        const allowedSerials = null;

        const foundSks = await superactivator.checkLicensecheckLicense(license, hwId, oem, expDate, nowDate, ip, allowedSerials, res)
        assert.equal(foundSks, '1');
    });
});

I get the error

ReferenceError: res is not defined

at Context. (test\superactivator.spec.js:23:130)

because I do not have res in test files. How can I solve this problem? I need to simply mock the response to check the returned values.

Thanks for help!

Solution

You can use Sinon to help you spy/stub res from express ie:

...

const superactivator = require('../helpers/superactivator');
const sinon = require('sinon'); // ----> use sinon
...

describe('checkLicense()', function () {
    it('sks ', async function () {
        // here I mock the request.body data
        const ip = '127.0.0.1';
        const license = "A2YyLM8i3G7feJt7Hlm8hxlYk";
        const hwId = "123490EN40";
        const oem = 12;
        const expDate = "2019-10-10";
        const nowDate = null; // "2018-09-05"
        const allowedSerials = null;
        const res = { 
          send: sinon.spy() // --> create spy for res.send method
        }

        const foundSks = await superactivator.checkLicensecheckLicense(license, hwId, oem, expDate, nowDate, ip, allowedSerials, res)
        assert.equal(foundSks, '1');
    });
});

Ref:
https://sinonjs.org/releases/v6.2.0/spies/

Answered By – deerawan

Answer Checked By – Willingham (AngularFixing Volunteer)

Leave a Reply

Your email address will not be published.