From edf5367c1c8b645c2910298e8fc8ad394f84be6e Mon Sep 17 00:00:00 2001 From: Sergii Mykyteiek Date: Tue, 5 Oct 2021 20:16:55 +0300 Subject: [PATCH] LT-7: Cover ttl controller with unit tests --- src/common/constants.ts | 1 + src/modules/ttl/ttl.controller.spec.ts | 155 +++++++++++++++++++++++++ src/modules/ttl/ttl.controller.ts | 15 +-- 3 files changed, 164 insertions(+), 7 deletions(-) create mode 100644 src/modules/ttl/ttl.controller.spec.ts diff --git a/src/common/constants.ts b/src/common/constants.ts index 0f809fc..5eb7edd 100644 --- a/src/common/constants.ts +++ b/src/common/constants.ts @@ -4,4 +4,5 @@ export const StatusCodes = { NO_CONTENT: 204, BAD_REQUEST: 400, NOT_FOUND: 404, + CONFLICT: 409, } \ No newline at end of file diff --git a/src/modules/ttl/ttl.controller.spec.ts b/src/modules/ttl/ttl.controller.spec.ts new file mode 100644 index 0000000..1548842 --- /dev/null +++ b/src/modules/ttl/ttl.controller.spec.ts @@ -0,0 +1,155 @@ +import 'reflect-metadata'; +import { Container } from 'typedi'; +import { TtlController } from './ttl.controller'; +import { TtlService } from './ttl.service'; +import { TtlValidationService } from './validation'; +import { StatusCodes } from '../../common/constants'; + +const mockResponse = { + json: jest.fn(), + status: jest.fn().mockImplementation(() => mockResponse), + send: jest.fn(), +}; + +describe('TtlController', () => { + let ttlController: TtlController; + let validateService: TtlValidationService; + let ttlService: TtlService; + + beforeEach(() => { + ttlController = Container.get(TtlController); + validateService = Container.get(TtlValidationService); + ttlService = Container.get(TtlService); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + describe('add item to store', () => { + it('When body does not pass validation -> should return 400', async () => { + const body = {}; + const mockRequest: any = { + body, + }; + const errors: any[] = [new Error('Wrong data')]; + jest.spyOn(validateService, 'validateBody').mockResolvedValue(errors); + jest.spyOn(ttlService, 'get').mockImplementation(() => ({}) as any); + jest.spyOn(ttlService, 'add').mockImplementation(() => ({}) as any); + + await ttlController.add(mockRequest, mockResponse); + + expect(mockResponse.status).toBeCalledWith(StatusCodes.BAD_REQUEST); + expect(mockResponse.send).toBeCalledWith({ errors }); + expect(mockResponse.json).not.toBeCalled(); + expect(ttlService.get).not.toBeCalled(); + expect(ttlService.add).not.toBeCalled(); + }); + + describe('When body passes validation', () => { + it('When key already exists -> should return 409', async () => { + const body = {}; + const mockRequest: any = { + body, + }; + const errors: any[] = []; + jest.spyOn(validateService, 'validateBody').mockResolvedValue(errors); + jest.spyOn(ttlService, 'get').mockImplementation(() => ({}) as any); + jest.spyOn(ttlService, 'add').mockImplementation(() => ({}) as any); + + await ttlController.add(mockRequest, mockResponse); + + expect(mockResponse.status).toBeCalledWith(StatusCodes.CONFLICT); + expect(mockResponse.send).not.toBeCalled(); + expect(mockResponse.json).toBeCalled(); + expect(ttlService.get).toBeCalled(); + expect(ttlService.add).not.toBeCalled(); + }); + + it('When key does not exist -> should return 201', async () => { + const body = {}; + const mockRequest: any = { + body, + }; + const errors: any[] = []; + const result: any = {} + jest.spyOn(validateService, 'validateBody').mockResolvedValue(errors); + jest.spyOn(ttlService, 'get').mockImplementation(() => null as any); + jest.spyOn(ttlService, 'add').mockImplementation(() => result); + + await ttlController.add(mockRequest, mockResponse); + + expect(mockResponse.status).toBeCalledWith(StatusCodes.CREATED); + expect(mockResponse.send).not.toBeCalled(); + expect(mockResponse.json).toBeCalledWith(result); + expect(ttlService.get).toBeCalled(); + expect(ttlService.add).toBeCalledWith(body); + }); + }); + }); + + describe('get item', () => { + it('When key does not exist -> should return 404', () => { + const params = { + key: '', + }; + const mockRequest: any = { + params, + }; + jest.spyOn(ttlService, 'get').mockImplementation(() => null as any); + + ttlController.get(mockRequest, mockResponse); + + expect(mockResponse.status).toBeCalledWith(StatusCodes.NOT_FOUND); + }); + + it('When key exists -> should return 200', () => { + const params = { + key: '', + }; + const mockRequest: any = { + params, + }; + const response: any = {}; + jest.spyOn(ttlService, 'get').mockImplementation(() => response); + + ttlController.get(mockRequest, mockResponse); + + expect(mockResponse.status).toBeCalledWith(StatusCodes.OK_RESPONSE); + expect(mockResponse.json).toBeCalledWith(response); + }); + }); + + describe('remove item', () => { + it('When key does not exist -> should return 404', function () { + const params = { + key: '', + }; + const mockRequest: any = { + params, + }; + const response: any = null; + jest.spyOn(ttlService, 'remove').mockImplementation(() => response); + + ttlController.remove(mockRequest, mockResponse); + + expect(mockResponse.status).toBeCalledWith(StatusCodes.NOT_FOUND); + }); + + it('When key exists -> should return 204', function () { + const params = { + key: '', + }; + const mockRequest: any = { + params, + }; + const response: any = {}; + jest.spyOn(ttlService, 'remove').mockImplementation(() => response); + + ttlController.remove(mockRequest, mockResponse); + + expect(mockResponse.status).toBeCalledWith(StatusCodes.NO_CONTENT); + expect(mockResponse.send).toBeCalled(); + }); + }); +}); diff --git a/src/modules/ttl/ttl.controller.ts b/src/modules/ttl/ttl.controller.ts index 92e8092..43a3423 100644 --- a/src/modules/ttl/ttl.controller.ts +++ b/src/modules/ttl/ttl.controller.ts @@ -3,6 +3,7 @@ import { Service } from 'typedi'; import { TtlService } from './ttl.service'; import { TtlResponse } from './ttl.dto'; import { TtlValidationService } from './validation'; +import { StatusCodes } from '../../common/constants'; @Service() export class TtlController { @@ -14,33 +15,33 @@ export class TtlController { async add(req: Request, res: Response): Promise> { const errors = await this.validationService.validateBody(req.body); if (errors.length > 0) { - return res.status(400).send({ errors }); + return res.status(StatusCodes.BAD_REQUEST).send({ errors }); } const data = this.ttlService.get(req.body.key); if (data) { - return res.status(409).json({ message: 'Key already exist' }); + return res.status(StatusCodes.CONFLICT).json({ message: 'Key already exist' }); } const result = this.ttlService.add(req.body); - return res.status(201).json(result); + return res.status(StatusCodes.CREATED).json(result); } get(req: Request, res: Response): Response { const result = this.ttlService.get(req.params.key); if (!result) { - return res.status(404).json({ message: 'Not found key' }) + return res.status(StatusCodes.NOT_FOUND).json({ message: 'Not found key' }) } - return res.status(200).json(result); + return res.status(StatusCodes.OK_RESPONSE).json(result); } remove(req: Request, res: Response): Response { const result = this.ttlService.remove(req.params.key); if (!result) { - return res.status(404).json({ message: 'Not found key' }) + return res.status(StatusCodes.NOT_FOUND).json({ message: 'Not found key' }) } - return res.status(204).send(); + return res.status(StatusCodes.NO_CONTENT).send(); } } -- GitLab