Monkey patching in NodeJS

Reading Time: 3 minutes

Hey guys, I am back with another blog in my series of blogs on mocking in nodeJS, so if you have read my last blog, in which we looked over how we can use sinon for testing in nodeJS to effectively mock and stub behaviours, so in this blog we would look over the concept of monkey patching to make things more testable, so let’s get started.

Monkey Patching

Monkey Patching in simple words could be seen as simply the dynamic replacement of attributes at runtime. Let’s take an example suppose your class/file has a private method or the method that’s not exported by module.exports, let’s say its name is __generateRandomHash() which returns a random value all together, and we have another method that calls it and this method, let’s say generateUserToken(), calls __generateRandomHash() and it is exported from the module, the file below would present a clearer picture

monkeyPatch.js

const __generateRandomHash = (arg) => {
     //Some complex logic/algo like below :p
 return arg + 1;
 };
 const generateUserToken = (userCreds, callback) => {
     let res = __generateRandomHash(userCreds)
         //Do some operation on results
         callback(res);
 };
 module.exports = {
     generateUserToken:generateUserToken
 };

Now, lets suppose you want to test/write testcases for generateUserToken() and we are not interesting in the result from __generateRandomHash() as it will always return a different value for every call, had __generateRandomHash() been a method from another dependency/library we could have easily mocked it using sinon or some other mocking frameworks, but in our case we can’t do it, so what to do in such a case,

don’t worry we can simply use an npm module rewire for such cases, let’s look at the spec file I have written to test the above method

patchSpec.js

const rewire = require('rewire');
let lamb = (value) => value * 10;
let util = require('../blog/monkey-patch.js');
let rewiredUtil = rewire('../blog/monkey-patch.js');


module.exports = ({describe, it, beforeEach, afterEach}) => {
    describe("Test rewire and spies", () => {

        beforeEach(() => {
            rewiredUtil.__set__("__generateRandomHash", lamb)
        });
        afterEach(() => {

        });


        it('should test without rewiring', async () => {
            util.generateUserToken(5, (res) => {
                console.log('in test');
                console.log(res);
                console.log('in test');
                res.should.equal(6);
            });
        });


        it('should test with rewiring', async () => {
            rewiredUtil.generateUserToken(5, (res) => {
                console.log('in test');
                console.log(res);
                console.log('in test');
                res.should.equal(50);
            });
        })

    })
};

Now let’s go through the file step by step, the first test case is simple it simple test the function with the actual call to __generateRandomHash() , now let’s talk about how second testcase is working so to monkey patch __generateRandomHash() we first created a method lamb() on line 2 so that it could be used in place of __generateRandomHash() then we need to rewire our module under test i.e; monkey-patch.js, see how we have rewired the file on line 4 and used it where we require to monkey patch, the code there in beforeEach block rewires the actual method against our method during test by using a method __set__()provided by rewire, so that’s all for this blog that the code above also available here drop a comment for any confusion or questions, happy coding :).


Knoldus-blog-footer-image

Written by 

Shubham Verma is a software consultant. He likes to explore new technologies and trends in the IT world. Shubham is familiar with programming languages such as Java, Scala, C, C++, HTML, Javascript and he is currently working on reactive technologies like Scala, Akka , spark and Kafka. His hobbies includes playing computer games and watching hollywood movies.