node.js - 如何使用 Jest 测试使用 TypeDI 作为依赖注入器的服务类
问题描述
我是使用 Jest 框架进行测试的新手,我对使用 Jest 测试框架测试我的服务类感到困惑。我已经实现了 TypeDI 来帮助解决依赖关系,我还实现了路由控制器。我需要有人向我展示如何使用我在下面粘贴的课程来测试我的课程。我不需要你测试所有的类方法,只需要几个例子就可以了。先感谢您。
import { NotFoundError, UnauthorizedError } from 'routing-controllers';
import { Service } from 'typedi';
import { BaseService } from '../../../services/base.service';
import { UserRegisterDTO, UserLoginDTO, OtpDTO, ResetPasswordDTO } from '../dto/auth.dto';
import { UsersRepository } from '../repositories/users.repository';
import ProfileUtilService from '../profile/profile_util.service';
import * as bcrypt from 'bcrypt';
import MessageBrooker from '../../../brooker/message_brooker';
import config from '../../../config';
import { sign } from 'jsonwebtoken';
import { OTPService } from '../otp/otp.service';
@Service()
export default class AuthService extends BaseService {
constructor(
private readonly userRepo: UsersRepository,
private readonly profileUtil: ProfileUtilService,
private readonly msgBrooker: MessageBrooker,
private readonly otpService: OTPService,
) {
super();
}
/**
* Login handler
* @param data login data
* @returns object
*/
async login(data: UserLoginDTO) {
const { email, password } = data;
//get user info
const user = await this.userRepo.getUserByEmail(email);
//check if user exists
if (!user) {
throw new UnauthorizedError('Invalid credentials');
}
//compare password
const passwordCheck = await bcrypt.compare(password, user.password);
//check if password match
if (!passwordCheck) {
throw new UnauthorizedError('Invalid credentials');
}
//sign JWT token
const token = this.generateToken(user.id, user.email);
return this.okResponse('Login valid', { token });
}
/**
* User registration handler
* @param user user registration data
* @returns
*/
async registerUser(user: UserRegisterDTO) {
//destruct user object
const { firstName, lastName, email } = user;
let { password } = user;
//encrypt password
password = bcrypt.hashSync(password, 10);
//create user record
const userObj = await this.userRepo.createUser({ email, password });
const userId = userObj.id;
//create profile
await this.profileUtil.createProfile({
user_id: userId,
firstName,
lastName,
});
//generate otp
const otp = await this.otpService.generateOTP(userId);
//send confirmation email
this.msgBrooker.sendMessage(
config.brookerChannels.email.auth.confirmation,
JSON.stringify({ firstName, lastName, email, otp }),
);
return this.okResponse('User created!');
}
/**
* Validate OTP
* @param data request body
* @returns JSON
*/
async validateOTP(data: OtpDTO) {
//1. check geneeated tokenk
const { userId, code } = data;
//check if otp is valid
await this.checkOTP(userId, code);
return this.okResponse('OTP validated');
}
/**
* Validates OPT and activates user account
* @param data request body
*/
async confirmEmail(data: OtpDTO) {
const { userId, code } = data;
//check if otp is valid
await this.checkOTP(userId, code);
//activate acount
const userData = this.userRepo.activateAccount(userId);
if (!userData) {
throw new NotFoundError('User not found');
}
return this.okResponse('Account activated');
}
/**
* Send forget password email with OTP
* @param email
* @returns JSON
*/
async forgotPassword(email: string) {
const data = this.userRepo.getUserByEmail(email);
if (!data) {
throw new NotFoundError('User not found');
}
//generate otp
const otp = await this.otpService.generateOTP(data.id);
//generate token
const token = this.generateToken(data.id, data.email);
//send pasword reset email
this.msgBrooker.sendMessage(
config.brookerChannels.email.auth.passwordReset,
JSON.stringify({
firstName: data.profile.firstName,
lastName: data.profile.lastName,
email: data.email,
otp,
}),
);
return this.okResponse('Password reset email sent', { token });
}
/**
* Update user password via OTP
* @param data
* @param userId
* @returns JSON
*/
async resetPassword(data: ResetPasswordDTO, userId: string) {
//validate OTP
await this.checkOTP(userId, data.code);
//encrypt password
const password = bcrypt.hashSync(data.password, 10);
//update account
const userData = await this.userRepo.updateAccount({ password }, userId);
if (!userData) {
throw new NotFoundError('User not found');
}
return this.okResponse('Password updated');
}
/**
* Update user password
* @param password
* @param userId
* @returns JSON
*/
async updateUserPassword(password: string, userId: string) {
//encrypt password
password = bcrypt.hashSync(password, 10);
//update account
const userData = await this.userRepo.updateAccount({ password }, userId);
if (!userData) {
throw new NotFoundError('User not found');
}
return this.okResponse('Password updated');
}
/**
* Generate JWT token
* @param userId user id
* @param email user email
* @returns string
*/
private generateToken(userId: string, email: string, duration?: string) {
return sign(
{
data: { email, id: userId },
},
config.jwtSecret,
{ expiresIn: duration ?? '1h' },
);
}
/**
* validate OTP
* @param userId
* @param code
*/
private async checkOTP(userId: string, code: number) {
const otp = await this.otpService.validateOTP(userId, code);
if (!otp) {
throw new UnauthorizedError('OTP not found');
}
}
}
请我需要帮助。
解决方案
推荐阅读
- python - 使用以下几种格式的正则表达式提取日期
- android - Android Web 视图未加载此静态 Html
- pandas - Dask - 如何节省内存,例如通过部分读取 csv?
- c++ - 有没有办法在 c++ 中确定标准输入内容的大小(以字节为单位)?
- postgresql - 如何为 postgresql db 创建多个列分区,一个用于时间范围,一个用于特定传感器 ID?
- javascript - 旋转 div 然后扩展
- angular - 获取值后来自订阅的 Angular/Typescript 处理结果
- kotlin - NavigationDrawer 和 SwipeViewTabs 中的 ViewPager2 不能为 null
- flask - 在一个页面中提供多个图像和 PDF 文件,而不是来自静态文件夹
- mysql - 如何将随机作业分配到 Mysql 中的代理列表?