Внутренняя ошибка сервера — Не удается прочитать свойство «sendMail» неопределенного

#typescript #jestjs #integration-testing #nodemailer #tsyringe

Вопрос:

Я запускаю интеграционные тесты с шуткой, чтобы проверить отправку электронных писем для восстановления пароля пользователю.

В моих случаях использования я внедряю службу отправки электронной почты (с помощью ethereal, nodemailer) с помощью tsyringe. Экземпляр этой службы имеет тип registerInstance , позволяющий создать клиента сразу после запуска приложения.

 container.registerInstance<IMailProvider>('EtherealMailProvider', new EtherealMailProvider());
 

Выполнение запроса через бессонницу, ответ успешен, и электронное письмо отправлено, но то же самое не происходит в интеграционных тестах. У кого-нибудь есть какие-нибудь идеи, почему?

Это ошибка, которую я получаю:

   {
     status: 'error',
     message: "Internal server error - Cannot read property 'sendMail' of undefined"
  }
 

При использовании звоните в службу электронной почты:

 import { resolve } from 'path';
import { inject, injectable } from 'tsyringe';
import { v4 as uuidV4 } from 'uuid';

import { IUsersRepository } from '@modules/accounts/repositories/IUsersRepository';
import { IUsersTokensRepository } from '@modules/accounts/repositories/IUsersTokensRepository';
import { IDateProvider } from '@shared/container/providers/DateProvider/IDateProvider';
import { IMailProvider } from '@shared/container/providers/MailProvider/IMailProvider';
import { AppError } from '@shared/errors/AppError';

@injectable()
class SendForgotPasswordMailUseCase {
  constructor(
    @inject('UsersRepository')
    private usersRepository: IUsersRepository,
    @inject('UsersTokensRepository')
    private usersTokensRepository: IUsersTokensRepository,
    @inject('DayJsDateProvider')
    private dateProvider: IDateProvider,
    @inject('EtherealMailProvider')
    private mailProvider: IMailProvider
  ) {}

  async execute(email: string): Promise<void> {
    const user = await this.usersRepository.findByEmail(email);

    if (!user) throw new AppError('User does not exists!');

    const token = uuidV4();

    const expires_date = this.dateProvider.addHours(3);

    await this.usersTokensRepository.create({
      refresh_token: token,
      user_id: user.id,
      expires_date,
    });

    const templatePath = resolve(__dirname, '..', '..', 'views', 'emails', 'forgotPassword.hbs');

    const variables = {
      name: user.name,
      link: `${process.env.FORGOT_MAIL_URL}${token}`,
    };

    await this.mailProvider.sendMail(email, 'Recovery Password', variables, templatePath);
  }
}

export { SendForgotPasswordMailUseCase };
 

Служба электронной почты:

 import { resolve } from 'path';
import { inject, injectable } from 'tsyringe';
import { v4 as uuidV4 } from 'uuid';

import { IUsersRepository } from '@modules/accounts/repositories/IUsersRepository';
import { IUsersTokensRepository } from '@modules/accounts/repositories/IUsersTokensRepository';
import { IDateProvider } from '@shared/container/providers/DateProvider/IDateProvider';
import { IMailProvider } from '@shared/container/providers/MailProvider/IMailProvider';
import { AppError } from '@shared/errors/AppError';

@injectable()
class SendForgotPasswordMailUseCase {
  constructor(
    @inject('UsersRepository')
    private usersRepository: IUsersRepository,
    @inject('UsersTokensRepository')
    private usersTokensRepository: IUsersTokensRepository,
    @inject('DayJsDateProvider')
    private dateProvider: IDateProvider,
    @inject('EtherealMailProvider')
    private mailProvider: IMailProvider
  ) {}

  async execute(email: string): Promise<void> {
    const user = await this.usersRepository.findByEmail(email);

    if (!user) throw new AppError('User does not exists!');

    const token = uuidV4();

    const expires_date = this.dateProvider.addHours(3);

    await this.usersTokensRepository.create({
      refresh_token: token,
      user_id: user.id,
      expires_date,
    });

    const templatePath = resolve(__dirname, '..', '..', 'views', 'emails', 'forgotPassword.hbs');

    const variables = {
      name: user.name,
      link: `${process.env.FORGOT_MAIL_URL}${token}`,
    };

    await this.mailProvider.sendMail(email, 'Recovery Password', variables, templatePath);
  }
}

export { SendForgotPasswordMailUseCase };
 

The controller in the application has the only function of receiving the email from request.body and passing it to useCase.

Вот ссылка на обновленный репозиторий: код находится в ветке integration_tests_for_sending_password_reset_mail

https://github.com/i-ramoss/rentx/tree/integration_tests_for_sending_password_reset_mail