findUserById

This commit is contained in:
sbriat 2023-07-24 10:13:27 +02:00
parent cc170779cb
commit 979ea5e98f
6 changed files with 241 additions and 0 deletions

View File

@ -0,0 +1,17 @@
import { IQueryHandler, QueryHandler } from '@nestjs/cqrs';
import { FindUserByIdQuery } from './find-user-by-id.query';
import { Inject } from '@nestjs/common';
import { USER_REPOSITORY } from '@modules/user/user.di-tokens';
import { UserRepositoryPort } from '../../ports/user.repository.port';
import { UserEntity } from '@modules/user/core/domain/user.entity';
@QueryHandler(FindUserByIdQuery)
export class FindUserByIdQueryHandler implements IQueryHandler {
constructor(
@Inject(USER_REPOSITORY)
private readonly userRepository: UserRepositoryPort,
) {}
async execute(query: FindUserByIdQuery): Promise<UserEntity> {
return await this.userRepository.findOneById(query.id);
}
}

View File

@ -0,0 +1,10 @@
import { QueryBase } from '@mobicoop/ddd-library';
export class FindUserByIdQuery extends QueryBase {
readonly id: string;
constructor(id: string) {
super();
this.id = id;
}
}

View File

@ -0,0 +1,7 @@
import { IsNotEmpty, IsString } from 'class-validator';
export class FindUserByIdRequestDto {
@IsString()
@IsNotEmpty()
id: string;
}

View File

@ -0,0 +1,46 @@
import { Controller, UsePipes } from '@nestjs/common';
import { QueryBus } from '@nestjs/cqrs';
import { GrpcMethod, RpcException } from '@nestjs/microservices';
import { NotFoundException } from '@mobicoop/ddd-library';
import { RpcExceptionCode } from '@mobicoop/ddd-library';
import { RpcValidationPipe } from '@mobicoop/ddd-library';
import { UserMapper } from '@modules/user/user.mapper';
import { FindUserByIdRequestDto } from './dtos/find-user-by-id.request.dto';
import { UserResponseDto } from '../dtos/user.response.dto';
import { UserEntity } from '@modules/user/core/domain/user.entity';
import { FindUserByIdQuery } from '@modules/user/core/application/queries/find-user-by-id/find-user-by-id.query';
@UsePipes(
new RpcValidationPipe({
whitelist: false,
forbidUnknownValues: false,
}),
)
@Controller()
export class FindUserByIdGrpcController {
constructor(
protected readonly mapper: UserMapper,
private readonly queryBus: QueryBus,
) {}
@GrpcMethod('UserService', 'FindOneById')
async findOnebyId(data: FindUserByIdRequestDto): Promise<UserResponseDto> {
try {
const user: UserEntity = await this.queryBus.execute(
new FindUserByIdQuery(data.id),
);
return this.mapper.toResponse(user);
} catch (e) {
if (e instanceof NotFoundException) {
throw new RpcException({
code: RpcExceptionCode.NOT_FOUND,
message: e.message,
});
}
throw new RpcException({
code: RpcExceptionCode.UNKNOWN,
message: e.message,
});
}
}
}

View File

@ -0,0 +1,58 @@
import { Test, TestingModule } from '@nestjs/testing';
import { UserEntity } from '@modules/user/core/domain/user.entity';
import { FindUserByIdQueryHandler } from '@modules/user/core/application/queries/find-user-by-id/find-user-by-id.query-handler';
import { USER_REPOSITORY } from '@modules/user/user.di-tokens';
import { FindUserByIdQuery } from '@modules/user/core/application/queries/find-user-by-id/find-user-by-id.query';
const now = new Date('2023-06-21 06:00:00');
const user: UserEntity = new UserEntity({
id: 'c160cf8c-f057-4962-841f-3ad68346df44',
props: {
firstName: 'John',
lastName: 'Doe',
email: 'john.doe@email.com',
phone: '+33611223344',
},
createdAt: now,
updatedAt: now,
});
const mockUserRepository = {
findOneById: jest.fn().mockImplementation(() => user),
};
describe('find-user-by-id.query-handler', () => {
let findUserByIdQueryHandler: FindUserByIdQueryHandler;
beforeAll(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
{
provide: USER_REPOSITORY,
useValue: mockUserRepository,
},
FindUserByIdQueryHandler,
],
}).compile();
findUserByIdQueryHandler = module.get<FindUserByIdQueryHandler>(
FindUserByIdQueryHandler,
);
});
it('should be defined', () => {
expect(findUserByIdQueryHandler).toBeDefined();
});
describe('execution', () => {
it('should return a user', async () => {
const findUserbyIdQuery = new FindUserByIdQuery(
'dd264806-13b4-4226-9b18-87adf0ad5dd1',
);
const user: UserEntity = await findUserByIdQueryHandler.execute(
findUserbyIdQuery,
);
expect(user.getProps().lastName).toBe('Doe');
});
});
});

View File

@ -0,0 +1,103 @@
import { NotFoundException } from '@mobicoop/ddd-library';
import { RpcExceptionCode } from '@mobicoop/ddd-library';
import { FindUserByIdGrpcController } from '@modules/user/interface/grpc-controllers/find-user-by-id.grpc.controller';
import { UserMapper } from '@modules/user/user.mapper';
import { QueryBus } from '@nestjs/cqrs';
import { RpcException } from '@nestjs/microservices';
import { Test, TestingModule } from '@nestjs/testing';
const mockQueryBus = {
execute: jest
.fn()
.mockImplementationOnce(() => '200d61a8-d878-4378-a609-c19ea71633d2')
.mockImplementationOnce(() => {
throw new NotFoundException();
})
.mockImplementationOnce(() => {
throw new Error();
}),
};
const mockUserMapper = {
toResponse: jest.fn().mockImplementationOnce(() => ({
firstName: 'John',
lastName: 'Doe',
email: 'john.doe@email.com',
phone: '+33611223344',
})),
};
describe('Find User By Id Grpc Controller', () => {
let findUserbyIdGrpcController: FindUserByIdGrpcController;
beforeAll(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
{
provide: QueryBus,
useValue: mockQueryBus,
},
{
provide: UserMapper,
useValue: mockUserMapper,
},
FindUserByIdGrpcController,
],
}).compile();
findUserbyIdGrpcController = module.get<FindUserByIdGrpcController>(
FindUserByIdGrpcController,
);
});
afterEach(async () => {
jest.clearAllMocks();
});
it('should be defined', () => {
expect(findUserbyIdGrpcController).toBeDefined();
});
it('should return a user', async () => {
jest.spyOn(mockQueryBus, 'execute');
jest.spyOn(mockUserMapper, 'toResponse');
const response = await findUserbyIdGrpcController.findOnebyId({
id: '6dcf093c-c7db-4dae-8e9c-c715cebf83c7',
});
expect(response.firstName).toBe('John');
expect(mockQueryBus.execute).toHaveBeenCalledTimes(1);
expect(mockUserMapper.toResponse).toHaveBeenCalledTimes(1);
});
it('should throw a dedicated RpcException if user is not found', async () => {
jest.spyOn(mockQueryBus, 'execute');
jest.spyOn(mockUserMapper, 'toResponse');
expect.assertions(4);
try {
await findUserbyIdGrpcController.findOnebyId({
id: 'ac85f5f4-41cd-4c5d-9aee-0a1acb176fb8',
});
} catch (e: any) {
expect(e).toBeInstanceOf(RpcException);
expect(e.error.code).toBe(RpcExceptionCode.NOT_FOUND);
}
expect(mockQueryBus.execute).toHaveBeenCalledTimes(1);
expect(mockUserMapper.toResponse).toHaveBeenCalledTimes(0);
});
it('should throw a generic RpcException', async () => {
jest.spyOn(mockQueryBus, 'execute');
jest.spyOn(mockUserMapper, 'toResponse');
expect.assertions(4);
try {
await findUserbyIdGrpcController.findOnebyId({
id: '53c8e7ec-ef68-42bc-ba4c-5ef3effa60a6',
});
} catch (e: any) {
expect(e).toBeInstanceOf(RpcException);
expect(e.error.code).toBe(RpcExceptionCode.UNKNOWN);
}
expect(mockQueryBus.execute).toHaveBeenCalledTimes(1);
expect(mockUserMapper.toResponse).toHaveBeenCalledTimes(0);
});
});