8

I am having issues writing unit test for the following setup as a jira.js file (in a node.js module):

var rest = require('restler'); // https://www.npmjs.com/package/restler

module.exports = function (conf) {
    var exported = {};

    exported.getIssue = function (issueId, done) {
        ...

        rest.get(uri).on('complete', function(data, response) {
        ...
    };

    return exported;
};

Now, i want to write unit test for my getIssue function. 'restler' is a REST client through which i make REST calls to the JIRA API to get a JIRA issue via my code.

So to be able to test createIssue(..), I want to be able to mock the 'rest' var in my Jasmine unit tests.

How can i mock this method? Please give me some pointers so that i can go ahead. I have tried using rewire but i have failed.

This is what i have so far which does not work (ie. getIssue method turns out to be undefined):

var rewire       = require("rewire");
var EventEmitter = require('events').EventEmitter;
var emitter      = new EventEmitter();
var cfg          = require("../../../config.js").Configuration;
var jiraModule   = rewire("../lib/jira")(cfg);
var sinon        = require("sinon");
var should       = require("should");

// https://github.com/danwrong/restler
var restMock = {
    init : function () {
        console.log('mock initiated'+JSON.stringify(this));

    },
    postJson : function (url, data, options) {
        console.log('[restler] POST url='+url+', data= '+JSON.stringify(data)+
        'options='+JSON.stringify(options));
        emitter.once('name_of_event',function(data){
            console.log('EVent received!'+data);
        });
        emitter.emit('name_of_event', "test");
        emitter.emit('name_of_event');
        emitter.emit('name_of_event');
    }, 
    get : function (url, options) {
        console.log('[restler] GET url='+url+'options='+JSON.stringify(options));
    },
    del : function (url, options) {
        console.log('[restler] DELETE url='+url+'options='+JSON.stringify(options));
    },
    putJson : function (url, data, options) {
        console.log('[restler] PUT url='+url+', data= '+JSON.stringify(data)+
        'options='+JSON.stringify(options));
    }
};

var cfgMock = {
    "test" : "testing"
};

jiraModule.__set__("rest", restMock);
jiraModule.__set__("cfg", cfgMock);

console.log('mod='+JSON.stringify(jiraModule.__get__("rest")));

describe("A suite", function() {
it("contains spec with an expectation", function() {
    restMock.init();
    restMock.postJson(null, null, null);

console.log(cfg.jira);

    // the following method turns out to be undefined but when i console.log out the jiraModule, i see the entire code outputted from that file
    jiraModule.getIssue("SRMAPP-130", function (err, result) {
        console.log('data= '+JSON.stringify(result));
     });

    expect(true).toBe(true);
});
});

If someone can guide me on how to mock the 'rest' require dependency & unit test this method that will be very helpful.

Also, how should i mock the 'conf' being passed to module.exports?

thanks

Rookie
  • 5,179
  • 13
  • 41
  • 65

1 Answers1

7

You could use proxyquire or mockery to stub/mock the dependencies.

In the below example I have used proxyquire. Hope it helps.


/* ./src/index.js */
var rest = require('restler');

module.exports = function (conf) {
  var exported = {};

  exported.getIssue = function (issueId, done) {
    var uri = '';
    var reqObj = '';
    var service = {
      auth : ''
    };

    rest.postJson(uri, reqObj, service.auth).on('complete', function(data, response) {
      done(data, response);
    });
  };

  return exported;
};

/* ./test/index.js */
var proxyquire  =  require('proxyquire');
var assert      =  require('chai').assert;
var restlerStub = {
  postJson: function() {
    return {
      on: function(event, callback) {
        callback('data', 'response');
      }
    }
  }
}

var index = proxyquire('../src/index', {'restler': restlerStub})();

describe('index', function() {
  it('should return the desired issue', function(done) {
    var issue = index.getIssue('issueId', function(data, response) {
      assert.equal(data, 'data');
      assert.equal(response, 'response');
      done();
    })
  });
});

/* ./package.json */
{
  "scripts": {
    "test": "mocha"
  },
  "dependencies": {
    "restler": "^3.4.0"
  },
  "devDependencies": {
    "chai": "^3.4.1",
    "mocha": "^2.3.4",
    "proxyquire": "^1.7.3"
  }
}
Sarbbottam
  • 5,410
  • 4
  • 30
  • 41
  • 1
    Jasmine-node is tagged, why are you using mocha? – Alexandr Lazarev Nov 18 '15 at 06:34
  • Opps, I did not notice that, however mocking the dependency has nothing to do with the test framework. – Sarbbottam Nov 18 '15 at 06:35
  • hello, thanks for the guidance!! how do i pass in the conf if i am using proxyquire? I need to mock conf as well....which is taken as an argument by module.exports.. – Rookie Nov 18 '15 at 06:36
  • `var index = proxyquire('../src/index', {'restler': restlerStub})(conf);` – Sarbbottam Nov 18 '15 at 06:37
  • thanks! this explanation looks promising. One more thing before i try out and see if this works. I am not sure how to fire the 'complete' event for testing (if you look at the rest call, it throws an event). Will the stub for 'restlerSTub' given above work in this case? or do i have to use eventemitter and emit an event from my restlerStub function? – Rookie Nov 18 '15 at 06:45
  • `rest.postJson().on()` could be comprehended as `rest.postJson()` returns and `object` which has a `on` method; `{on: function(){}}`, this on method is subsequently called. If you see the stub its doing the same. You could use `EventEmitter` too. – Sarbbottam Nov 18 '15 at 06:51
  • thanks sarbbottam. This is really a great suggestion! I will test this out and let you know if it worked for me. really appreciate the help! – Rookie Nov 18 '15 at 06:55
  • excellent! this worked like a charm! thanks a ton for the advise sarbbottam. you rock :) – Rookie Nov 18 '15 at 07:17
  • You have to use jest mocks if you are using jest framework – morhook Jun 19 '19 at 07:58