Stubbing with proxyquire

10,004

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
                }
        });
Share:
10,004
hyprstack
Author by

hyprstack

The only people who ever fail are those who stop trying.

Updated on June 04, 2022

Comments

  • hyprstack
    hyprstack almost 2 years

    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();
            }});
    
        });
    });
    
  • hyprstack
    hyprstack almost 9 years
    when I run the test it returns TypeError: Object #<Object> has no method 'connect'
  • Ivan Fraixedes
    Ivan Fraixedes almost 9 years
    @hyprstack you can also stub connect than create a function and return the the object, then you'll be able to check the calls to connect
  • hyprstack
    hyprstack almost 9 years
    I updated my question with my full test. However I am getting the following error: 1) invoicer "before all" hook: TypeError: Should wrap property of object
  • Ivan Fraixedes
    Ivan Fraixedes almost 9 years
    No really sure, but it seems that the lines of code inside before throw an error, you should look for what is wrong inside
  • hyprstack
    hyprstack almost 9 years
    Its the line where sendMailStub = sinon.stub(emailjs, 'send'); The same error happens if I try to stub connect
  • Ivan Fraixedes
    Ivan Fraixedes almost 9 years
    You may have a clash between require emailjs in your test and call proxiquire with emailjs after and the same with fs; I think that you don't need them in your test so don't require them just stub them in proxiquire
  • hyprstack
    hyprstack almost 9 years
    You're right about that. I was stubbing them before proxyquire, that's why I was getting that error, instead of having them: readFileStub = sinon.stub(); sendStub = sinon.stub(); But it is still not stubbing emailjs. I have updated my question with my latest test
  • hyprstack
    hyprstack almost 9 years
    Instead it is returning an error Error: timeout of 2000ms execeeded
  • hyprstack
    hyprstack almost 9 years
    I think the problem might be that connect is not a function. How would one get around that issue?
  • hyprstack
    hyprstack almost 9 years
    This is the error it returns now: Uncaught TypeError: Property 'connect' of object #<Object> is not a function
  • hyprstack
    hyprstack almost 9 years
    True. I should actually be connectStub = sinon.stub().returns({ send: sendStub });