
Ruben's Blog | Ռուբենի Բլոգը
🔙 ..Testing email sending with Jest, nodemailer, Node and TypeScript 📩
Ever since I started to do Test-driven development(TDD) I am encountered various issues regarding which I cannot find definitive solutions, so I will write my own.
Last time, I couldn’t make nodemailer to work with jest.
So imagine you have this REST API endpoint under /api/send-email
you want to test.
import nodemailer from 'nodemailer';
const transporter = nodemailer.createTransport({
host: 'smtp.host.com',
port: 465,
secure: true,
auth: {
user: 'REPLACE-WITH-YOUR-ALIAS@YOURDOMAIN.COM',
pass: 'REPLACE-WITH-YOUR-GENERATED-PASSWORD',
},
});
const sendEmail = async (req: Request, res: Response) => {
const email = 'some-email@mail.com';
try {
await transporter.sendMail({
from: `"Test email content" <${process.env.EMAIL_URL}>`,
to: email,
subject: 'Hello from test email.',
text: `This is a test email, thank you.`,
html: `
This is a test email,
<br>
thank you.
`,
});
res.status(200).send({ message: 'Please check your email.' });
} catch (err) {
res.status(400).send({ error: { message: 'Something went wrong.' } });
}
};
Now let’s test it with Jest.
import { htmlToText } from 'html-to-text'; // in order to test html content
// for some js reason this doesn't work with let
var sendMailMock: jest.Mock;
// mocking nodemailer
jest.mock('nodemailer', () => {
return {
__esModule: true, // this line makes it work!
default: {
createTransport: () => {
// be sure to use promise
sendMailMock = jest.fn((mail: Mail) => Promise.resolve(mail));
return { sendMail: sendMailMock };
},
},
};
});
beforeEach(() => {
sendMailMock.mockClear();
});
describe('{email test}', () => {
test('POST /api/send-email should send an email', async () => {
const email = 'some-email@mail.com'
const body = {};
const response = await request(app)
.post('/api/send-email')
.send(body);
expect(response.status).toBe(200);
// checking the argument that was passed to the sendMail function
const [args] = sendMailMock.mock.calls[0] as any;
expect(sendMailMock).toHaveBeenCalled();
expect(args.to).toBe(email);
expect(args.subject).toBe('Hello from test email.');
const htmlText = htmlToText(args.html);
expect(htmlText).not.toBe('');
const emailContaingTexts = [
'This is a test email,',
'thank you.'
];
emailContaingTexts.forEach((emailContaingText) =>
expect(htmlText).toContain(emailContaingText),
);
});
});
This way you can test any aspect of email sending.
Please give me feedback or make a comment on whatever help me improve. ❤️
Blog Menu
- 💼 hire my consultancy
- ℹ️ about me
- 📰 rss
- ⌛️ Spend a day with me
- tech and life
- 📝 blogs
- 2025-05-28
Am I Growing? 🌱
Since I’ve started my journey of entrepreneurship, I’ve been doing podcasts, creating communities, and organizing meetups. Did I grow? I t...
- 2025-05-20
1 EURO for a Ride 💶
To become a taxi driver, you must possess a driver’s license, purchase a car for at least 2500 EURO, maintain the vehicle, buy fuel, and pay fee...
- 2025-05-18
Eurovision and context 🏆️
Yesterday, I watched Eurovision. It’s clear that everyone wants their country to win, while some countries hope others don’t win. Neighbor...
- 2025-05-16
Spending 5 Minutes to Make a Point 📌
This blog post is an exercise. I want to make a point, and for that, I will need to do some research and tell a story. Telling a story Henry Ford was ...
- 2025-05-14
Non technical founders, Visionary Builders Community 👯♀️
This is my third community. I’m starting to understand how it works. People with similar interests or challenges tend to have similar insights a...
- 2025-05-13
2nd CTO Event Is Soon 🪞
What’s about it? I host Armenian CTO Community. We have already 109 members there. First event hosted 21 members! I am doing this for over 9 mo...
- 2025-05-12
Reducing the Friction to Post 🌪️
Eliminating the reasons I don’t blog, one by one. Opening the editor is a friction, writing is a friction, pushing is a friction, but I can make...
- 2025-05-07
Consistency and Time ⏲️
Do I have time to blog? Every time I wrote I will blog every day, I’ve reflected on this commitment in several posts: In I Need to Revisit My Bl...
- 2024-12-29
Then the Journey Is Not About Winning 🏆️
Winning is the target, but the journey is never about winning. You cannot be sure the path is correct. Even with guidance, there is a chance it’...
- 2024-12-28
Free Consultancy 💆🏻
Nobody buys it. When I provide it everyone is happy. Why? Maybe people don’t understand the offer, which is completely understandable. What I of...
- See all...
- 🔗 links