node.js mock sendmailer transporter inside function

Issue

Im working with an node handler in AWS lambda and i need to make another files with integration tests from that function, but i cant mock the transporter with sinon or mockery.

the index.js function:

var nodemailer = require('nodemailer');

exports.handler = (event, context, callback) =>
{
  var transporter=createTransporter();
    transporter.sendMail(data, function (error, success) {
        console.log(error);
        response = getResponse(404, error);
    }
    callback(null, response);
    });
}

function createTransporter() {
return nodemailer.createTransport({
    service: "SMTP",
    auth: {
        user: "XXXX@XXX",
        pass: "XXXX"
    }
});
}

the purpose is to mock the function createTransporter() so that it doesnt send any email when it is called in javascript file test with mocha and expect:

var mockery = require('mockery');
var nodemailerMock = require('nodemailer-mock');
var index = require("../index.js");

describe("The handler function tests", function () {
    before(function () {
        mockery.enable({
            warnOnUnregistered: false
        });
        mockery.registerMock('nodemailer', nodemailerMock);
    });

  it('JSON error html ', function () {
        var callback = function (name, response) {
            expect(JSON.stringify(response.statusCode)).to.be('404');
        };
        var context = {};
        index.handler(event, context, callback);
    });
});

Solution

I wrote nodemailer-mock 🙂

The problem you’re having is that you are calling var index = require("../index.js"); before you are mocking nodemailer via mockery, so it is already in the module cache. I included // Make sure anything that uses nodemailer is loaded here, after it is mocked... in the examples in the README, but should probably make it more clear.

Move the require("../index.js") after nodemailer is mocked and it will be work as expected.

var mockery = require('mockery');
var nodemailerMock = require('nodemailer-mock');

// don't require here since you will get the real nodemailer and cache it
var index;

describe("The handler function tests", function () {
    before(function () {
        mockery.enable({
            warnOnUnregistered: false
        });
        mockery.registerMock('nodemailer', nodemailerMock);

        // do the require() here after nodemailer is mocked
        index = require("../index.js");
    });

    // your tests here should now use nodemailer-mock
    it('JSON error html ', function () {
        var callback = function (name, response) {
            expect(JSON.stringify(response.statusCode)).to.be('404');
        };
        var context = {};
        index.handler(event, context, callback);
    });
});

Another option is to use the { useCleanCache: true } option with calls to mockery.resetCache();, though I have had mixed results. See Controlling the Module Cache in the mockery documentation.

Answered By – doublesharp

Answer Checked By – Marilyn (AngularFixing Volunteer)

Leave a Reply

Your email address will not be published.