How do I sinon.stub a nested method with a callback?

3.8k Views Asked by At

I need to test a method that includes a sub-method which makes a call to an API server. I’d like to stud this internal sub-method, but I can’t seem to do that. Here’s an example:

var requests = require('./requests.js');

var utilityClass = {
  methodCreatesObject: function (callback) {

    // Here’s the method I’m trying to stub:
    requests.makeCallToAPI(requestObject, function (err, responseFromAPI) {

      doSomethingWithResponse(responseFromAPI, function (err, finalObject) {

        if (err) {
          callback(err, null);
        } else {
          callback(null, finalObject); // <- Want to test the value of finalObject
        }

      });

    });

  }
}

So, my test looks something like this (updated to show loading requests.js before utility.js):

var should   = require('should'),
    Joi      = require('joi'),
    sinon    = require('sinon'),
    requests = require('../lib/modules/requests.js'),
    utility  = require('../lib/modules/utility.js')
    ;

// Start my tests:
describe('Method', function () {

  before(function () {
    var fakeAPIresponse = { ... }
    sinon.stub(requests, 'makeCallToAPI').yield(null, fakeAPIresponse);
  });

  it('should produce a well-formed finalObject', function (done) {
    utilityClass.methodCreatesObject(function (err, response) {
      if (err) {
        done(err);
      } else {
        response.should.do.this.or.that;
        done();
      }
    });
  });

});

As I understand it, .yields() should try to run the first callback it detects in the arguments and feed its own arguments to it (resulting in doSomethingWithResponse(responseFromAPI, function () {...})). However, when running mocha, I’m getting an error indicating that the API server could not be reached, which suggests that the real requests.makeCallToAPI() is being called, and not my stub.

I must be missing something. What am I doing wrong here?

1

There are 1 best solutions below

10
On BEST ANSWER

Where are you requiring the request.js? You will need to require request.js before you load up the module you want to test.

Edit 1: Using sinon.js

Here is a gist of what I meant: https://gist.github.com/limianwang/1114249de99c6a189384

Edit 2: Using proxyquire

If you are intending to test simply the utilities without concern of what actually happens within the requests.makeAPICall, you can use something like proxyquire to do the trick. If you are concerned with the actual logic within requests.js, you can use sinon.stub to stub out the actual request.get api.