Jeff
Jeff

Reputation: 36553

Sinon NodeJS stub only for module under test

I have a module under test which uses https to PUT data to a response URL. Before doing so, it makes calls to the AWS SDK. I do not want to stub the calls that AWS SDK makes using https, but I do want to stub the call to https.post that my module under test uses (it's an AWS Lambda unit test if that matters).

Consider the following test code

    describe('app', function () {
        beforeEach(function () {
            this.handler = require('../app').handler; 
            this.request = sinon.stub(https, 'request');
        });

        afterEach(function () {
            https.request.restore();
        });

        describe('#handler()', function () {
            it('should do something', function (done) {

                var request = new PassThrough();
                var write = sinon.spy(request, 'write');

                this.request.returns(request);

                var event = {...};

                var context = {
                    done: function () {
                        assert(write.withArgs({...}).calledOnce);
                        done();
                    }
                }

                this.handler(event, context);
            });
        });
    });

And my module under test (app.js)

var aws = require("aws-sdk");
var promise = require("promise");
exports.handler = function (event, context) {

    var iam = new aws.IAM();
    promise.denodeify(iam.getUser.bind(iam))().then(function (result) {
        ....
        sendResponse(...);
    }, function (err) {
        ...
    });

};

// I only want to stub the use of https in THIS function, not the use of https by the AWS SDK itself
function sendResponse(event, context, responseStatus, responseData) {

    var https = require("https");
    var url = require("url");

    var parsedUrl = url.parse(event.ResponseURL);
    var options = {
       ...
    };

    var request = https.request(options, function (response) {
       ...
        context.done();
    });

    request.on("error", function (error) {
        ...
        context.done();
    });

    // write data to request body
    request.write(...);
    request.end();
}

How can I accomplish this?

Upvotes: 0

Views: 294

Answers (1)

duncanhall
duncanhall

Reputation: 11431

You could use nock to mock specific HTTP/S requests, rather than function calls.

With nock, you can setup URL and request matchers that will allow requests through that don't match what you've defined.

Eg:

nock('https://www.something.com')
    .post('/the-post-path-to-mock')
    .reply(200, 'Mocked response!');

This would only intercept POST calls to https://www.something.com/the-post-path-to-mock, responding with a 200, and ignore other requests.

Nock also provides many options for mocking responses or accessing the original request data.

Upvotes: 1

Related Questions