Mocking email function in nodejs

久未见 提交于 2019-12-03 01:50:20
rizidoro

You can use a 'Stub' transport layer on your test instead of SMTP.

var stubMailer = require("nodemailer").createTransport("Stub"),
    options = {
        from: "from@email.com",
        to: "to@email.com",
        text: "My Message!"
    };

   stubMailer.sendMail(options, function(err, response){
     var message = response.message;
   })

So, in that case, 'message' will be the email in text format. Something like this:

MIME-Version: 1.0
X-Mailer: Nodemailer (0.3.43; +http://www.nodemailer.com/)
Date: Fri, 25 Feb 2014 11:11:48 GMT
Message-Id: <123412341234.e23232@Nodemailer>
From: from@email.com
To: to@email.com
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable

My Message!

For more examples, take a look at nodemailer test suite: https://github.com/andris9/Nodemailer/blob/master/test/nodemailer-test.js

expectEmail simply hooks into the transport layer, and expects you to identify the email ( return true if this is the email you are expecting ) by looking at the sentEmail contents.

In this case, return sentEmail.to === 'dave@testco.com' should suffice.

Keep in mind however, this module was designed in an environment where tests are ran in a random order and concurrently. You should propably randomize your data heavily to prevent collisions and false positives. BTW we use something like: var to = Date.now().toString(36) + Faker.Internet.email();

Alongkorn Chetasumon

This example works fine for me

======== myfile.js ========

// SOME CODE HERE

transporter.sendMail(mailOptions, (err, info) => {
  // PROCESS RESULT HERE
});

======== myfile.spec.js (unit test file) ========

const sinon = require('sinon');
const nodemailer = require('nodemailer');
const sandbox = sinon.sandbox.create();

describe('XXX', () => {
  afterEach(function() {
    sandbox.restore();
  });

  it('XXX', done => {
    const transport = {
      sendMail: (data, callback) => {
        const err = new Error('some error');
        callback(err, null);
      }
    };
    sandbox.stub(nodemailer, 'createTransport').returns(transport);

    // CALL FUNCTION TO TEST

    // EXPECT RESULT
  });
});

You can directly mock the sendMail function but it's not obvious how to access it from the tests. A Mailer instance is returned when you create a transport so you need to directly import that class in to your test.

const Mailer = require('nodemailer/lib/mailer')

Then you can mock or stub the sendMail method on the prototype in the usual way. Using Jasmine, you can do it like this:

beforeEach(function () {
  spyOn(Mailer.prototype, 'sendMail').and.callFake(function (mailOptions, cb) {
    cb(null, true)
  })
})

The callFake ensures that the sendMail's callback is still executed encase you need to test what happens next. You can easily simulate an error by passing a first argument to cb: cb(new Error('Email failed'))

Now that the mock is set up, you can check everything is working as intended:

expect(Mailer.prototype.sendMail).toHaveBeenCalled()
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!