Я front-end разработчик, пытаюсь написать unit-тесты на NestJS, дошел до этапа, когда они уже могут запускаться, но выдают неправильный результат (все время проходят без ошибок).
Например, я передаю в метод create данные:
{ login: 'ffff', password: 'fafa4636fwafw' }
, в результате я должен получить тот же результат (просто для примера), но в тесте я прокидываю эти данные
{ id:1, login: 'ffff', password: 'fafa4636fwafw' roles:[]}
, но я передаю в результат для сравнения совсем другой:
login: 'ffff',
password: 'fafa4636',
roles: [],
id: 1,
и тест проходит без ошибок
Я думаю, что проблема в моковом сервисе, но не знаю как ее решить.
Вот код:
import { Test, TestingModule } from '@nestjs/testing';
import { CreateUserPayload } from 'src/modules/user/user.payload';
import { User } from '../entities/user.entity';
import { UserController } from '../modules/user/user.controller';
import { UserService } from '../modules/user/user.service';
describe('UserController', () => {
let userController: UserController;
let userService: UserService;
class MockUserService {
create(payload: CreateUserPayload) {
return { ...payload, id: 1, roles:[] };
}
}
beforeEach(async () => {
const moduleRef = await Test.createTestingModule({
controllers: [UserController],
providers: [UserService],
})
.overrideProvider(UserService)
.useClass(MockUserService)
.compile();
userService = moduleRef.get<UserService>(UserService);
userController = moduleRef.get<UserController>(UserController);
});
describe('create', () => {
it('should create new user repository', async () => {
const result: User = {
login: 'ffff',
password: 'fafa4636',
roles: [],
id: 1,
};
jest.spyOn(userService, 'create').mockImplementation(async (payload) => {
console.log('pay', payload);
console.log('res', result);
return result;
});
expect(await userController.create({ login: 'ffff', password: 'fafa4636fwafw' }).catch((e) => expect(e).toEqual(result)));
});
});
});
Результат выполнения:
Фрагменты модуля user:
user.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { UserController } from './user.controller';
import { User } from '../../entities/user.entity';
import { UserService } from './user.service';
import { Role } from 'src/entities/role.entity';
@Module({
imports: [TypeOrmModule.forFeature([User, Role])],
controllers: [UserController],
providers: [UserService],
})
export class UserModule {}
user.controller.ts
import { Body, Controller, Delete, Get, Param, Post, Put } from '@nestjs/common';
import { CreateUserPayload, UpdateUserPayload } from './user.payload';
import { UserService } from './user.service';
@Controller('/api/users')
export class UserController {
constructor(private userService: UserService) {}
@Post()
create(@Body() payload: CreateUserPayload) {
return this.userService.create(payload);
}
}
user.service.ts
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { Repository } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm';
import { CreateUserPayload, UpdateUserPayload } from './user.payload';
import { User } from '../../entities/user.entity';
import { Role } from '../../entities/role.entity';
@Injectable()
export class UserService {
constructor(private userRepository: Repository<User>) {}
async create(payload: CreateUserPayload): Promise<User> {
const errors = [];
let response: Object = { success: true };
if (!payload.login || payload?.login?.trim() === '') {
errors.push('login was not provided');
}
if (payload.password && payload?.password?.trim() !== '') {
if (!payload.password.match(/\d+/g)) {
errors.push('password must contains at least one numeric character');
}
if (!payload.password.match(/[A-Z]/g)) {
errors.push('password must contains at least one capital letter');
}
} else {
errors.push('password was not provided');
}
if (errors.length) {
response = { ...response, success: false, status: HttpStatus.BAD_REQUEST, errors };
throw new HttpException(response, HttpStatus.BAD_REQUEST);
}
const user = this.userRepository.create({ ...payload, roles: [] });
await this.userRepository.save(user);
return { ...user, ...response };
}
}
user.entity.ts
import { Entity, Column, PrimaryGeneratedColumn, OneToMany, JoinColumn, ManyToOne, ManyToMany, JoinTable } from 'typeorm';
import { Role } from './role.entity';
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
login: string;
@Column()
password: string;
@ManyToMany((type) => Role, (role) => role.users)
@JoinTable({
name: 'user_role',
joinColumns: [{ name: 'user_id' }],
inverseJoinColumns: [{ name: 'role_id' }],
})
roles: Role[];
}
user.payload.ts
export class CreateUserPayload {
readonly login: string;
readonly password: string;
}
export class UpdateUserPayload {
readonly login?: string;
readonly password?: string;
readonly roles?: string[];
}