Security News
GitHub Removes Malicious Pull Requests Targeting Open Source Repositories
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
nodemailer-mock
Advanced tools
Easy as pie nodemailer
mock for unit testing your Node.js applications.
From SecretParty.io with ❤️.
npm install nodemailer-mock --save-dev
yarn add -D nodemailer-mock
Depending on your mock configuration nodemailer-mock
may, or may not, have access to nodemailer
when it is loaded. For example, using mockery
you can replace nodemailer
with require('nodemailer-mock')
, however in jest
you will need to inject nodemailer
using module.exports = require('nodemailer-mock').getMockFor(require('nodemailer'));
Use with test suites like jest
and mocha
. There are some special methods available on the mocked module to help with testing. They are under the .mock
key of the mocked nodemailer
.
NodemailerMock.mock
functionsreset: () => void
getSentMail: () => Mail.Options[]
getCloseCallCount: () => number
transporter.close()
was called across all instancessetShouldFailOnce: (isSet?: boolean) => void
transporter.sendMail()
or transport.send()
isShouldFailOnce: () => boolean
setShouldFailOnce(?)
setShouldFail: (isFail?: boolean) => void
transporter.sendMail()
or transport.send()
true
, return errorfalse
, return successisShouldFail: () => boolean
setShouldFail()
setShouldFailCheck: (check: CheckMailMessageOrNull) => void
transporter.sendMail()
or transport.send()
true
, return errorfalse
, return successtype CheckMailMessageOrNull = ((email: MailMessage) => boolean) | null
getShouldFailCheck: () => CheckMailMessageOrNull
MailMessage
or null
if it is not setsetMockedVerify: (isMocked: boolean) => void
transport.verify()
should be mocked or passed through to nodemailer
, defaults to true
.
true
, use a mocked callbackfalse
, pass through to a real nodemailer
transportisMockedVerify: () => boolean
setMockedVerify(?)
setMockedClose: (isMocked: boolean) => void
transporter.close()
should be passed through to the underlying transport, defaults to true
.isMockedClose: () => boolean
true
the underlying transport is not used, when false
the call is passed through.setSuccessResponse: (response: string) => void
transporter.sendMail()
or transport.send()
getSuccessResponse: () => string
setFailResponse: (error: Error) => void
Error
that is returned in the callback for transporter.sendMail()
or transport.send()
getFailResponse: () => Error
Error
valuescheduleIsIdle: (isIdle: boolean, timeout: number) => void
transporter.isIdle()
instancessetIsIdle: (isIdle: boolean) => void
transporter.isIdle()
instancessetUnmockedUsePlugins: (isUnmockUsePlugins: boolean) => void
default false
transporter.use()
be run outside the mock?isUnmockedUsePlugins: () => boolean
setUnmockedUsePlugins(?)
NodemailerMockTransporter.mock
functionsgetPlugins: () => { [key: string]: Mail.PluginFunction<Mail.Options>[] }
transporter.use()
as arrays, keyed by stepgetCloseCallCount: () => number
close()
has been called on this transporter. this number is not reset with the mock.setIdle(isIdle: boolean): void
transporter.isIdle()
and emits an idle
event when the isIdle
argument is true
.The mocked module behaves in a similar fashion to other transports provided by nodemailer
.
setup test
const nodemailermock = require('nodemailer-mock');
const transport = nodemailermock.createTransport();
// the email you want to send
const email = ... // <-- your email here
use nodestyle callbacks
// send with nodestyle callback
transport.sendMail(email, function(err, info) {
if (err) {
return console.log('Error!', err, info);
}
return console.log('Success!', info);
}
// verify with nodestyle callback
transport.verify(function(err, success) {
if (err) {
return console.log('Error!', err);
}
return console.log('Success!', success);
});
use promises
// send with promises
transport.sendMail(email)
.then(function(info) {
console.log('Success!', info);
})
.catch(function(err) {
console.log('Error!', err);
});
// verify with promises
transport.verify()
.then(function(success) {
console.log('Success!', success);
});
.catch(function(err) {
console.log('Error!', err);
});
use async/await
// send an email with async / wait
try {
const info = await transport.sendMail(email);
} catch (err) {
console.log('Error!', err);
}
// verify with async / wait
try {
const info = await transport.verify();
} catch (err) {
console.log('Error!', err);
}
To use nodemailer-mock
in your tests you will need to mock nodemailer
with it. There are working examples using jest
and jest
in the ./examples/
folder of the project. The jest
code is in ./examples/__mocks__
and ./examples/__tests__
, and the mocha
tests are in ./examples/test
. Run the examples with npm run example:jest
and npm run example:mocha
. Both JavaScript and TypeScript example tests are provided.
To mock nodemailer
using jest
create a file called ./__mocks__/nodemailer.js
that exports the mocked module:
/**
* Jest Mock
* ./__mocks__/nodemailer.js
**/
// load the real nodemailer
const nodemailer = require('nodemailer');
// pass it in when creating the mock using getMockFor()
const nodemailermock = require('nodemailer-mock').getMockFor(nodemailer);
// export the mocked module
module.exports = nodemailermock;
Once the mock file is created all calls to nodemailer
from your tests will return the mocked module. To access to mock functions, just load it in your test file.
/**
* Jest Test
* ./__tests__/my-test.js
**/
const { mock } = require('nodemailer');
test('Send an email using the mocked nodemailer', async () => {
/* ... run your tests that send emails here */
// check the mock for our sent emails
const sentEmails = mock.getSentMail();
// there should be one
expect(sentEmails.length).toBe(1);
// and it should match the to address
expect(sentEmails[0].to).toBe('justin@to.com');
});
Using typescript you can coerce the NodemailerMock type.
/**
* Jest Test
* ./__tests__/my-test.js
**/
import { expect, test } from '@jest/globals';
// 'nodemailer' is automatically mocked in ./__mocks__/nodemailer.js
import * as nodemailer from 'nodemailer';
import { NodemailerMock } from 'nodemailer-mock';
const { mock } = nodemailer as unknown as NodemailerMock;
test('Send an email using the mocked nodemailer + typescript', async () => {
/* ... run your tests that send emails here */
// check the mock for our sent emails
const sentEmails = mock.getSentMail();
// there should be one
expect(sentEmails.length).toBe(1);
// and it should match the to address
expect(sentEmails[0].to).toBe('justin@to.com');
});
Here is an example of using a mocked nodemailer
class in a mocha
test using mockery
. Make sure that any modules that require()
's a mocked module must be called AFTER the module is mocked or node will use the unmocked version from the module cache. Note that this example uses async/await
. See the module tests for additional example code.
/**
* Mocha Test / Mockery Mock
* ./test/my-test.js
**/
const { expect } = require('chai');
const mockery = require('mockery');
const nodemailermock = require('nodemailer-mock');
describe('Tests that send email', async () {
/* This could be an app, Express, etc. It should be
instantiated *after* nodemailer is mocked. */
let app = null;
before(async () {
// Enable mockery to mock objects
mockery.enable({
warnOnUnregistered: false,
});
/* Once mocked, any code that calls require('nodemailer')
will get our nodemailermock */
mockery.registerMock('nodemailer', nodemailermock)
/*
##################
### IMPORTANT! ###
##################
*/
/* Make sure anything that uses nodemailer is loaded here,
after it is mocked just above... */
const moduleThatRequiresNodemailer = require('module-that-requires-nodemailer');
});
afterEach(async () {
// Reset the mock back to the defaults after each test
nodemailermock.mock.reset();
});
after(async () {
// Remove our mocked nodemailer and disable mockery
mockery.deregisterAll();
mockery.disable();
});
it('should send an email using nodemailer-mock', async () {
// call a service that uses nodemailer
const response = ... // <-- your email code here
// a fake test for something on our response
expect(response.value).to.equal('value');
// get the array of emails we sent
const sentMail = nodemailermock.mock.getSentMail();
// we should have sent one email
expect(sentMail.length).to.equal(1);
// check the email for something
expect(sentMail[0].property).to.equal('foobar');
});
it('should fail to send an email using nodemailer-mock', async () {
// tell the mock class to return an error
const err = new Error('My custom error');
nodemailermock.mock.setShouldFailOnce();
nodemailermock.mock.setFailResponse(err);
// call a service that uses nodemailer
var response = ... // <-- your code here
// a fake test for something on our response
expect(response.error).to.equal(err);
});
/* this will not work with jest as all nodemailers are mocked */
it('should verify using the real nodemailer transport', async () {
// tell the mock class to pass verify requests to nodemailer
nodemailermock.mock.setMockedVerify(false);
// call a service that uses nodemailer
var response = ... // <-- your code here
/* calls to transport.verify() will be passed through,
transporter.send() is still mocked */
});
});
FAQs
Easy as pie nodemailer mock for unit testing your Node.js applications
The npm package nodemailer-mock receives a total of 16,900 weekly downloads. As such, nodemailer-mock popularity was classified as popular.
We found that nodemailer-mock demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
Security News
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
Security News
Node.js will be enforcing stricter semver-major PR policies a month before major releases to enhance stability and ensure reliable release candidates.