Stubbing with proxyquire

hyprstack picture hyprstack · Apr 29, 2015 · Viewed 9.9k times · Source

How would I stub the following module with proxyquire and sinon:

var email = require("emailjs").server.connect.send();

I did the following, but its not working, because when I try to trigger an error within send() it still sends the email.

sendMailStub = sinon.stub(email, "send");    
testedModule = proxyquire('../index.js', {
                'email': {
                    'server': {
                        'send': sendMailStub
                        }
                    }
            });

And also tried:

testedModule = proxyquire('../index.js', {
            email: {send: sendMailStub}
        });

This is the full test so far, which fails:

var chai = require('chai');
var sinonChai = require("sinon-chai");
var sinon = require('sinon');
chai.use(sinonChai);
var proxyquire = require('proxyquire');
var testedModule;
var expect = chai.expect;



describe('invoicer', function () {

    var nock = require('nock');

    var ResponseOptions = {
        username: "Peter Pan",
        user_address_line_1: "Never Never Land",
        user_address_line_2: "Tree-house 99",
        user_post_code: "E4 9BY",
        delivery_address_line_1: "Hook's Boat",
        delivery_address_line_2: "Dock 69",
        delivery_post_code: "SE2 4C",
        order_number: "234234234",
        order_date: "20/12/2090",
        dispatch_date: "20/12/2090",
        items: [
            {
                product_name: "Fairy Dust",
                brand: "Airy fairy",
                quantity: 5,
                total: 2000
            },
            {
                product_name: "Pirate Sword",
                brand: "Pirate's Bay",
                quantity: 8,
                total: 2000
            }
        ],
        grand_total: 4000,
        user_email: "[email protected]"
    }

    var mailOptions = {
        text: "Hello World"
    }

    var scope = nock("http://somewhere.com")
        .get("/orders")
        .reply(200, ResponseOptions);

    var sendStub, readFileStub, url, contextDoneSpy, obj, connectStub;

    before(function () {

        readFileStub = sinon.stub();
        sendStub = sinon.stub().withArgs(mailOptions).callsArgWith(1, null, contextDoneSpy);
        connectStub = sinon.stub().returns({
            send: sendStub
        });

        testedModule = proxyquire('../index', {
            'fs': {readFile: readFileStub},
            'emailjs': {
                'server': {
                    'connect': connectStub
                }
            }
        });

        url = "http://somewhere.com/orders";
        contextDoneSpy = sinon.spy();
        obj = {
            user: 'AKIAJMHSJRRYGKTE4TOQ',
            password: 'Ag3Nkpej8dxZ4DwYz2in/x8kUhN7Lh/BqXImB0+i+DWy',
            host: "email-smtp.eu-west-1.amazonaws.com",
            port: 587,
            tls: true,
            ssl: false
        }

        readFileStub.withArgs('./email.html').callsArgWith(1, null, 'file1');

        connectStub();
    });

    it("readFile and successful context.done were called", function (done) {
        testedModule.Invoicer(url, obj, { done: function () {
            contextDoneSpy.apply(null, arguments);
            expect(readFileStub).has.been.called;
            expect(contextDoneSpy).to.have.been.called;
            done();
        }});

    });
});

Answer

Ivan Fraixedes picture Ivan Fraixedes · Apr 29, 2015

Let's first fix the line where your described emailjs using the its documentation

require("emailjs").server.connect({
  /* Required server options */
}).send(function (err, message) {
  // This a function with a callback node convention signature
});

connect is a function and should receive some parameters, moreover send doesn't return any thing, basically call a callback

Proxyquire requires to use the same module name, so email should be emailjs, on the other hand you're wrong assigning the stub in proxiquire, it should be

connectStub = sinon.stub().returns(sendStub);
sendMailStub = sinon.stub(email, "send");    
testedModule = proxyquire('../index.js', {
            'emailjs': {
                'server': {
                    'connect': connectStub
                }
        });