在nodejs中模拟电子邮件功能

时间:2013-12-04 22:04:18

标签: node.js nodemailer

我已经建立了邮件功能并试图加强覆盖范围。试图测试它的一部分已被证明是棘手的,特别是这个mailer.smtpTransport.sendMail

var nodemailer = require('nodemailer')

var mailer = {}

mailer.smtpTransport = nodemailer.createTransport('SMTP', {
    'service': 'Gmail',
    'auth': {
        'XOAuth2': {
            'user': 'test@test.com',
            'clientId': 'googleClientID',
            'clientSecret': 'superSekrit',
            'refreshToken': '1/refreshYoSelf'
        }
    }
})
var mailOptions = {
    from: 'Some Admin <test@tester.com>',
}

mailer.verify = function(email, hash) {
    var emailhtml = 'Welcome to TestCo. <a href="'+hash+'">Click this '+hash+'</a>'
    var emailtxt = 'Welcome to TestCo. This  is your hash: '+hash
    mailOptions.to = email
    mailOptions.subject = 'Welcome to TestCo!'
    mailOptions.html = emailhtml
    mailOptions.text = emailtxt
    mailer.smtpTransport.sendMail(mailOptions, function(error, response){
        if(error) {
            console.log(error)

        } else {
            console.log('Message sent: '+response.message)
        }
    })
}

我不确定如何进行测试,特别是确保我的mailer.smtpTransport.sendMail函数传递正确的参数而不实际发送电子邮件。我正在尝试使用https://github.com/whatser/mock-nodemailer/tree/master,但我可能做错了。我应该嘲笑这个方法吗?

var _ = require('lodash')
var should = require('should')
var nodemailer = require('nodemailer')
var mockMailer = require('./helpers/mock-nodemailer')
var transport = nodemailer.createTransport('SMTP', '')

var mailer = require('../../../server/lib/account/mailer')

describe('Mailer', function() {
    describe('.verify()', function() {
        it('sends a verify email with a hashto an address when invoked', function(done) {
            var email ={
                'to': 'dave@testco.com',
                'html': 'Welcome to Testco. <a href="bleh">Click this bleh</a>',
                'text': 'Welcome to Testco. This  is your hash: bleh',
                'subject': 'Welcome to Testco!'
            }

            mockMailer.expectEmail(function(sentEmail) {
            return _.isEqual(email, sentEmail)
            }, done)
            mailer.verify('dave@testco.com','bleh')
            transport.sendMail(email, function() {})
    })
})

4 个答案:

答案 0 :(得分:16)

您可以在测试中使用“存根”传输层而不是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;
   })

因此,在这种情况下,'message'将是文本格式的电子邮件。像这样:

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!

有关更多示例,请查看nodemailer测试套件: https://github.com/andris9/Nodemailer/blob/master/test/nodemailer-test.js

答案 1 :(得分:2)

expectEmail只是挂钩到传输层,并希望您通过查看sentEmail内容来识别电子邮件(如果这是您期望的电子邮件,则返回true)。

在这种情况下,return sentEmail.to === 'dave@testco.com'就足够了。

但请记住,此模块是在一个以随机顺序同时运行测试的环境中设计的。您应该大量随机化您的数据,以防止碰撞和误报。顺便说一句,我们使用类似:var to = Date.now().toString(36) + Faker.Internet.email();

的内容

答案 2 :(得分:2)

此示例适用于我

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

// SOME CODE HERE

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

======== myfile.spec.js(单元测试文件)========

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

descript('XXX', () => {
  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
  });
});

答案 3 :(得分:1)

您可以直接模拟sendMail函数,但是如何从测试中访问它并不明显。创建传输时会返回Mailer实例,因此您需要直接将该类导入到测试中。

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

然后你可以用通常的方式在原型上模拟或存根sendMail方法。使用Jasmine,您可以这样做:

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

callFake确保sendMail的回调仍然执行,你需要测试接下来会发生什么。您可以通过将第一个参数传递给cb来轻松模拟错误:cb(new Error('Email failed'))

现在已经设置了模拟,您可以检查一切是否按预期工作:

expect(Mailer.prototype.sendMail).toHaveBeenCalled()