From fd783681badc196ae3af9a98588c7b5ce3b7df28 Mon Sep 17 00:00:00 2001 From: Mathis HERRIOT <197931332+0x485254@users.noreply.github.com> Date: Sat, 17 May 2025 00:19:07 +0200 Subject: [PATCH] test(persons.service): enhance test coverage and improve mock logic readability - Refactored test cases to use more precise assertions and enhanced expected data validation. - Added mock implementations for database operations and service dependencies to improve clarity. - Improved error handling test scenarios (e.g., NotFoundException cases). - Increased test consistency with additional checks on method call counts. --- .../persons/services/persons.service.spec.ts | 93 ++++++++++++++++--- 1 file changed, 82 insertions(+), 11 deletions(-) diff --git a/backend/src/modules/persons/services/persons.service.spec.ts b/backend/src/modules/persons/services/persons.service.spec.ts index f64783d..0f57fd0 100644 --- a/backend/src/modules/persons/services/persons.service.spec.ts +++ b/backend/src/modules/persons/services/persons.service.spec.ts @@ -82,10 +82,23 @@ describe('PersonsService', () => { metadata: {}, }; + // Expected values that will be passed to the database + const expectedPersonData = { + firstName: 'John', + lastName: 'Doe', + gender: 'MALE', + technicalLevel: 3, + hasTechnicalTraining: true, + frenchSpeakingLevel: 5, + oralEaseLevel: 'COMFORTABLE', + projectId: 'project1', + attributes: {}, + }; + const result = await service.create(createPersonDto); expect(mockDb.insert).toHaveBeenCalled(); - expect(mockDb.values).toHaveBeenCalledWith(createPersonDto); + expect(mockDb.values).toHaveBeenCalledWith(expectedPersonData); expect(result).toEqual(mockPerson); }); }); @@ -151,10 +164,30 @@ describe('PersonsService', () => { name: 'Jane Doe', }; + // Mock the findById method to return a person + const existingPerson = { + id: 'person1', + firstName: 'John', + lastName: 'Doe', + projectId: 'project1', + attributes: {}, + createdAt: new Date(), + updatedAt: new Date(), + }; + jest.spyOn(service, 'findById').mockResolvedValueOnce(existingPerson); + + // Expected values that will be passed to the database + const expectedUpdateData = { + firstName: 'Jane', + lastName: 'Doe', + updatedAt: expect.any(Date), + }; + const result = await service.update(id, updatePersonDto); + expect(service.findById).toHaveBeenCalledWith(id); expect(mockDb.update).toHaveBeenCalled(); - expect(mockDb.set).toHaveBeenCalled(); + expect(mockDb.set).toHaveBeenCalledWith(expectedUpdateData); expect(mockDb.where).toHaveBeenCalled(); expect(result).toEqual(mockPerson); }); @@ -165,10 +198,8 @@ describe('PersonsService', () => { name: 'Jane Doe', }; - mockDb.update.mockImplementationOnce(() => mockDbOperations); - mockDbOperations.set.mockImplementationOnce(() => mockDbOperations); - mockDbOperations.where.mockImplementationOnce(() => mockDbOperations); - mockDbOperations.returning.mockImplementationOnce(() => []); + // Mock the findById method to throw a NotFoundException + jest.spyOn(service, 'findById').mockRejectedValueOnce(new NotFoundException(`Person with ID ${id} not found`)); await expect(service.update(id, updatePersonDto)).rejects.toThrow(NotFoundException); }); @@ -178,6 +209,11 @@ describe('PersonsService', () => { it('should delete a person', async () => { const id = 'person1'; + // Mock the database to return a person + mockDb.delete.mockImplementationOnce(() => mockDbOperations); + mockDbOperations.where.mockImplementationOnce(() => mockDbOperations); + mockDbOperations.returning.mockImplementationOnce(() => [mockPerson]); + const result = await service.remove(id); expect(mockDb.delete).toHaveBeenCalled(); @@ -188,6 +224,7 @@ describe('PersonsService', () => { it('should throw NotFoundException if person not found', async () => { const id = 'nonexistent'; + // Mock the database to return no person mockDb.delete.mockImplementationOnce(() => mockDbOperations); mockDbOperations.where.mockImplementationOnce(() => mockDbOperations); mockDbOperations.returning.mockImplementationOnce(() => []); @@ -201,6 +238,17 @@ describe('PersonsService', () => { const projectId = 'project1'; const groupId = 'group1'; + // Mock project check + mockDb.select.mockImplementationOnce(() => mockDbOperations); + mockDbOperations.from.mockImplementationOnce(() => mockDbOperations); + mockDbOperations.where.mockImplementationOnce(() => [{ id: projectId }]); + + // Mock group check + mockDb.select.mockImplementationOnce(() => mockDbOperations); + mockDbOperations.from.mockImplementationOnce(() => mockDbOperations); + mockDbOperations.where.mockImplementationOnce(() => [{ id: groupId }]); + + // Mock persons query mockDb.select.mockImplementationOnce(() => mockDbOperations); mockDbOperations.from.mockImplementationOnce(() => mockDbOperations); mockDbOperations.innerJoin.mockImplementationOnce(() => mockDbOperations); @@ -208,11 +256,11 @@ describe('PersonsService', () => { const result = await service.findByProjectIdAndGroupId(projectId, groupId); - expect(mockDb.select).toHaveBeenCalled(); - expect(mockDb.from).toHaveBeenCalled(); + expect(mockDb.select).toHaveBeenCalledTimes(3); + expect(mockDb.from).toHaveBeenCalledTimes(3); expect(mockDb.innerJoin).toHaveBeenCalled(); - expect(mockDb.where).toHaveBeenCalled(); - expect(result).toEqual([{ person: mockPerson }]); + expect(mockDb.where).toHaveBeenCalledTimes(3); + expect(result).toEqual([mockPerson]); }); }); @@ -221,12 +269,31 @@ describe('PersonsService', () => { const personId = 'person1'; const groupId = 'group1'; + // Mock person check + mockDb.select.mockImplementationOnce(() => mockDbOperations); + mockDbOperations.from.mockImplementationOnce(() => mockDbOperations); + mockDbOperations.where.mockImplementationOnce(() => [mockPerson]); + + // Mock group check + mockDb.select.mockImplementationOnce(() => mockDbOperations); + mockDbOperations.from.mockImplementationOnce(() => mockDbOperations); + mockDbOperations.where.mockImplementationOnce(() => [mockGroup]); + + // Mock relation check + mockDb.select.mockImplementationOnce(() => mockDbOperations); + mockDbOperations.from.mockImplementationOnce(() => mockDbOperations); + mockDbOperations.where.mockImplementationOnce(() => []); + + // Mock relation creation mockDb.insert.mockImplementationOnce(() => mockDbOperations); mockDbOperations.values.mockImplementationOnce(() => mockDbOperations); mockDbOperations.returning.mockImplementationOnce(() => [mockPersonToGroup]); const result = await service.addToGroup(personId, groupId); + expect(mockDb.select).toHaveBeenCalledTimes(3); + expect(mockDb.from).toHaveBeenCalledTimes(3); + expect(mockDb.where).toHaveBeenCalledTimes(3); expect(mockDb.insert).toHaveBeenCalled(); expect(mockDb.values).toHaveBeenCalledWith({ personId, @@ -241,14 +308,16 @@ describe('PersonsService', () => { const personId = 'person1'; const groupId = 'group1'; + // Mock delete operation mockDb.delete.mockImplementationOnce(() => mockDbOperations); mockDbOperations.where.mockImplementationOnce(() => mockDbOperations); + mockDbOperations.where.mockImplementationOnce(() => mockDbOperations); mockDbOperations.returning.mockImplementationOnce(() => [mockPersonToGroup]); const result = await service.removeFromGroup(personId, groupId); expect(mockDb.delete).toHaveBeenCalled(); - expect(mockDb.where).toHaveBeenCalled(); + expect(mockDb.where).toHaveBeenCalledTimes(2); expect(result).toEqual(mockPersonToGroup); }); @@ -256,8 +325,10 @@ describe('PersonsService', () => { const personId = 'nonexistent'; const groupId = 'group1'; + // Mock delete operation to return no relation mockDb.delete.mockImplementationOnce(() => mockDbOperations); mockDbOperations.where.mockImplementationOnce(() => mockDbOperations); + mockDbOperations.where.mockImplementationOnce(() => mockDbOperations); mockDbOperations.returning.mockImplementationOnce(() => []); await expect(service.removeFromGroup(personId, groupId)).rejects.toThrow(NotFoundException);