Mocking Mailer Class with Jest
In this guide, we will explore how to mock a Mailer class in a Node.js application using Jest. This is particularly useful when you want to test email sending functionality triggered by specific events, such as a password reset.
Project Structure
Ensure your project is organized as follows:
project_root
-- __test__
---- server
------ services
-------- emails
---------- mailer.test.js
-- server
---- services
------ emails
-------- mailer.js
-------- __mocks__
---------- mailer.js
Mock File: __mocks__/mailer.js
Create a mock for the Mailer class in the __mocks__ directory. This mock will simulate the behavior of the actual Mailer class without sending real emails.
const Mailer = jest.genMockFromModule('Mailer');
function send(to, subject, body) {
return { to, subject, body };
}
Mailer.send = jest.fn(send);
module.exports = Mailer;
Test File: mailer.test.js
In your test file, you will set up an event emitter to trigger the password reset event and verify that the send method is called appropriately.
const EventEmitter = require('events');
const Mailer = require('../../../../server/services/emails/mailer');
test('should send an email when the password-reset event is triggered', () => {
const event = new EventEmitter();
event.on('password-reset', () => {
Mailer.send('user@example.com', 'Password Reset', 'Click here to reset your password.');
});
// Emit the password-reset event
event.emit('password-reset');
// Verify that the send method was called
expect(Mailer.send).toHaveBeenCalledWith('user@example.com', 'Password Reset', 'Click here to reset your password.');
});
Mailer Class: mailer.js
Here is the implementation of the Mailer class that uses Mailgun to send emails. This class will be mocked in your tests.
const mailgun = require('mailgun-js');
class Mailer {
constructor() {
this.mailgunInstance = mailgun({
apiKey: process.env.MAILGUN_API_KEY,
domain: process.env.MAILGUN_DOMAIN,
});
}
send(to, subject, body) {
return new Promise((resolve, reject) => {
this.mailgunInstance.messages().send({
from: 'Securely App <friendly-robot@securelyapp.com>',
to,
subject,
html: body,
}, (error, response) => {
if (error) {
return reject(error);
}
return resolve('Email sent successfully!');
});
});
}
}
module.exports = new Mailer();
Conclusion
By following this guide, you should be able to successfully mock the Mailer class and test its email sending functionality using Jest. This approach allows you to ensure your application behaves as expected without sending real emails during testing.