我正在使用 Jest 运行集成测试,以测试向用户发送密码恢复电子邮件。
在我的用例中,我使用 tsyringe 注入电子邮件发送服务(使用 ethereal、nodemailer)。该服务的实例属于类型registerInstance
,以便应用程序一启动就可以创建客户端。
container.registerInstance<IMailProvider>('EtherealMailProvider', new EtherealMailProvider());
通过 Insomnia 执行请求,响应成功并发送电子邮件,但在集成测试中不会发生同样的情况。有谁知道为什么?
这是我得到的错误:
{
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 };
应用程序中的控制器具有接收来自的电子邮件request.body
并将其传递给 useCase 的唯一功能。
这是更新存储库的链接: 代码在 integration_tests_for_sending_password_reset_mail 分支中
https://github.com/i-ramoss/rentx/tree/integration_tests_for_sending_password_reset_mail