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
var nodemailer = require('nodemailer')
var mailer = {}
mailer.smtpTransport = nodemailer.createTransport('SMTP', {
'service': 'Gmail',
'auth': {
'XOAuth2': {
'user': '[email protected]',
'clientId': 'googleClientID',
'clientSecret': 'superSekrit',
'refreshToken': '1/refreshYoSelf'
}
}
})
var mailOptions = {
from: 'Some Admin <[email protected]>',
}
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)
}
})
}
I'm unsure of how to go about testing, specifically ensuring that my mailer.smtpTransport.sendMail function is passing the correct parameters without actually sending the email. I'm trying to use https://github.com/whatser/mock-nodemailer/tree/master, but I'm probably doing it wrong. Should I be mocking out the method?
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': '[email protected]',
'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('[email protected]','bleh')
transport.sendMail(email, function() {})
})
})
You can use a 'Stub' transport layer on your test instead of SMTP.
var stubMailer = require("nodemailer").createTransport("Stub"),
options = {
from: "[email protected]",
to: "[email protected]",
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: [email protected]
To: [email protected]
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
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()
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 === '[email protected]'
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();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With