I'm currently grappling with the task of unit testing my Controller in an express app, but I seem to be stuck. Here are the code files I've been working with:
// CreateUserController.ts
import { Request, Response } from "express";
import { CreateUserService } from "../services/CreateUserService";
class CreateUserController {
async handle(request: Request, response: Response) {
try {
const { name, email, admin, password } = request.body;
const createUserService = new CreateUserService();
const user = await createUserService.execute({ name, email, admin, password });
return response.send(user);
} catch (error) {
return response.send({ error });
}
}
}
export { CreateUserController };
// CreateUserService.ts
import { getCustomRepository } from "typeorm";
import { UsersRepositories } from "../repositories/UsersRepositories";
import { hash } from "bcryptjs";
interface IUserRequest {
name: string;
email: string;
admin?: boolean;
password: string;
}
class CreateUserService {
async execute({ name, email, admin = false, password }: IUserRequest) {
const usersRepository = getCustomRepository(UsersRepositories);
if(!email) {
throw new Error('Incorrect e-mail.');
}
const userAlreadyExists = await usersRepository.findOne({ email });
if(userAlreadyExists) {
throw new Error('User already exists.');
}
const passwordHash = await hash(password, 8);
const user = usersRepository.create({ name, email, admin, password: passwordHash });
const savedUser = await usersRepository.save(user);
return savedUser;
}
}
export { CreateUserService };
// Users.ts
import { Entity, PrimaryColumn, Column, CreateDateColumn, UpdateDateColumn } from "typeorm";
import { Exclude } from "class-transformer";
import { v4 as uuid } from "uuid";
@Entity("users")
class User {
@PrimaryColumn()
readonly id: string;
@Column()
name: string;
@Column()
email: string;
@Column()
admin: boolean;
@Exclude()
@Column()
password: string;
@CreateDateColumn()
created_at: Date;
@UpdateDateColumn()
updated_at: Date;
constructor() {
if (!this.id) {
this.id = uuid();
}
}
}
export default User;
// UsersRepositories.ts
import { EntityRepository, Repository } from "typeorm";
import User from "../entities/User";
@EntityRepository(User)
class UsersRepositories extends Repository<User> {}
export { UsersRepositories };
I am keen on testing the CreateUserController, however, it appears that the current implementation may not be easily testable. Can anyone confirm?
// CreateUserController.unit.test.ts
import { CreateUserController } from "./CreateUserController";
import { getCustomRepository } from "typeorm";
import { UsersRepositories } from "../repositories/UsersRepositories";
import { hash } from "bcryptjs";
import { v4 as uuid } from "uuid";
describe('testando', () => {
it('primeiro it', async () => {
const userId = uuid();
const userData = {
name: 'Fulano',
email: '<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="0e6b636f67624e6a206d6163">[email protected]</a>',
password: '123456',
admin: true
};
const returnUserData = {
id: userId,
name: 'Fulano',
email: '<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="71141c10181d31155f121e1e">[email protected]</a>',
password: await hash('123456', 8),
admin: true,
created_at: new Date(),
updated_at: new Date()
};
jest.spyOn(getCustomRepository(UsersRepositories), 'save').mockImplementation(async () => returnUserData);
const user = await CreateUserController.handle(userData);
});
});
Currently encountering some errors, but this is what I've managed to put together so far.