How to test email sending with Mailhog on local?

1.2k views Asked by At

Setup mailhog with docker-compose like:

version: '3'
services:
  mailhog:
    image: mailhog/mailhog
    ports:
      - 8025:8025
      - 1025:1025

It's possible to access localhost:8025 from browser. Maybe the SMTP server 1025 also works but don't know how to confirm it.

In a NestJS application, for testing the email code as:

@Module({
  imports: [NodeMailerModule],
  providers: [MailHogEmailRepository],
  exports: [MailHogEmailRepository],
})
class MailHogEmailRepositoryModule {}

@Module({
  imports: [MailHogEmailRepositoryModule],
  providers: [
    {
      provide: EmailRepository,
      useFactory: (
        config: ConfigService,
        mailHog: MailHogEmailRepository,
      ) => {
        return mailHog;
        }
      },
      inject: [ConfigService, MailHogEmailRepository],
    },
  ],
  exports: [EmailRepository],
})
export class EmailRepositoryModule {}

MailHogEmailRepository send with nodemailer:

@Injectable()
export class MailHogEmailRepository implements EmailRepository {
  constructor(
    @Inject(NodeMailerToken) private readonly nodemailer: Transporter,
  ) {}

  async send(email: Email) {
    const options = {
      to: email.to,
      from: email.from,
      subject: email.subject,
    };
    await this.nodemailer.sendMail(options);
  }
}

nodemailer config:

import { Module } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { createTransport } from 'nodemailer';

export const NodeMailerToken = Symbol('nodemailer');

@Module({
  providers: [
    {
      provide: NodeMailerToken,
      useFactory: (config: ConfigService) =>
        createTransport({
          host: 'localhost',
          port: 1025,
          secure: true,
        }),
      inject: [ConfigService],
    },
  ],
  exports: [NodeMailerToken],
})
export class NodeMailerModule {}

In test source, it always timeout:

import { Test, TestingModule } from '@nestjs/testing';
import request from 'supertest';

import {
  FastifyAdapter,
  NestFastifyApplication,
} from '@nestjs/platform-fastify';

describe('Test sender', () => {
  let app: NestFastifyApplication;

  beforeEach(async () => {
    const moduleFixture: TestingModule = await Test.createTestingModule({
      imports: [AppModule],
    }).compile();

    app = moduleFixture.createNestApplication(new FastifyAdapter());
    await app.init();
    await app.getHttpAdapter().getInstance().ready();
  });

  describe('/handler (POST)', () => {
    describe('should send data to mail server', () => {
      it('success', () => {
        const message = ...

        return request(app.getHttpServer())
          .post('/handler')
          .send({ message })
          .expect(200);
      });
    });
  });
});

$ npm run test

thrown: "Exceeded timeout of xxx ms for a test.
Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test."

It seems the test case couldn't access the mailhog server running in docker container. How to set it correctly?

0

There are 0 answers