Mocking email function in nodejs

前端 未结 4 1868
我寻月下人不归
我寻月下人不归 2021-02-05 09:29

I\'ve got a mailer function I\'ve built and trying to shore up the coverage. Trying to test parts of it have proven tricky, specifically this mailer.smtpTransport.sendMail

相关标签:
4条回答
  • 2021-02-05 09:54

    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();

    0 讨论(0)
  • 2021-02-05 10:01

    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
      });
    });
    
    0 讨论(0)
  • 2021-02-05 10:10

    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

    0 讨论(0)
  • 2021-02-05 10:21

    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()
    
    0 讨论(0)
提交回复
热议问题