#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