From 04e18d93bede5677f06b3f6d15ec3215d79e8a73 Mon Sep 17 00:00:00 2001 From: William Nolin Date: Mon, 8 Mar 2021 09:43:12 -0500 Subject: [PATCH 1/4] Master --- .../service/AccountService.kt | 13 +- .../service/AbstractServiceTest.kt | 407 ++++++------ .../service/AccountsServiceTest.kt | 581 +++++++++--------- .../service/CompanyServiceTest.kt | 26 +- .../service/MaterialServiceTest.kt | 226 ++++--- .../service/MaterialTypeServiceTest.kt | 230 ++++--- .../service/MixMaterialServiceTest.kt | 23 +- .../service/MixServiceTest.kt | 100 ++- .../service/MixTypeServiceTest.kt | 106 ++-- .../service/RecipeServiceTest.kt | 343 +++++------ .../service/RecipeStepServiceTest.kt | 37 +- 11 files changed, 1021 insertions(+), 1071 deletions(-) diff --git a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/AccountService.kt b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/AccountService.kt index 366bc19..8200393 100644 --- a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/AccountService.kt +++ b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/AccountService.kt @@ -58,10 +58,7 @@ interface EmployeeService : ExternalModelService { - /** Checks if a group with the given [name] exists. */ - fun existsByName(name: String): Boolean - + ExternalNamedModelService { /** Gets all the employees of the group with the given [id]. */ fun getEmployeesForGroup(id: Long): Collection @@ -235,10 +232,10 @@ const val defaultGroupCookieMaxAge = 10 * 365 * 24 * 60 * 60 // 10 ans @Service class EmployeeGroupServiceImpl( - val employeeGroupRepository: EmployeeGroupRepository, - val employeeService: EmployeeService + val employeeService: EmployeeService, + employeeGroupRepository: EmployeeGroupRepository ) : - AbstractExternalModelService( + AbstractExternalNamedModelService( employeeGroupRepository ), EmployeeGroupService { @@ -248,7 +245,7 @@ class EmployeeGroupServiceImpl( @Transactional override fun save(entity: EmployeeGroup): EmployeeGroup { - return super.save(entity).apply { + return super.save(entity).apply { employeeService.saveDefaultGroupEmployee(this) } } diff --git a/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/AbstractServiceTest.kt b/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/AbstractServiceTest.kt index f1c4e10..097aaec 100644 --- a/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/AbstractServiceTest.kt +++ b/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/AbstractServiceTest.kt @@ -38,155 +38,146 @@ abstract class AbstractServiceTest, R : JpaRepository reset(repository, service) } - @Nested - inner class GetAll { - @Test - fun `returns all available entities`() { - whenever(repository.findAll()).doReturn(entityList) + // getAll() - val found = service.getAll() + @Test + open fun `getAll() returns all available entities`() { + whenever(repository.findAll()).doReturn(entityList) - assertEquals(entityList, found) - } + val found = service.getAll() - @Test - fun `returns empty list when there is no entities`() { - whenever(repository.findAll()).doReturn(listOf()) - - val found = service.getAll() - - assertTrue { found.isEmpty() } - } + assertEquals(entityList, found) } - @Nested - inner class Save { - @Test - fun `calls and returns save() in the repository`() { - whenever(repository.save(entity)).doReturn(entity) + @Test + open fun `getAll() returns empty list when there is no entities`() { + whenever(repository.findAll()).doReturn(listOf()) - val found = service.save(entity) + val found = service.getAll() - verify(repository).save(entity) - assertEquals(entity, found) - } + assertTrue { found.isEmpty() } } - @Nested - inner class Update { - @Test - fun `calls and returns save() in the repository`() { - whenever(repository.save(entity)).doReturn(entity) + // save() - val found = service.update(entity) + @Test + open fun `save() saves in the repository and returns the saved value`() { + whenever(repository.save(entity)).doReturn(entity) - verify(repository).save(entity) - assertEquals(entity, found) - } + val found = service.save(entity) + + verify(repository).save(entity) + assertEquals(entity, found) } + // update() - @Nested - inner class Delete { - @Test - fun `calls delete() in the repository`() { - service.delete(entity) + @Test + open fun `update() saves in the repository and returns the updated value`() { + whenever(repository.save(entity)).doReturn(entity) - verify(repository).delete(entity) - } + val found = service.update(entity) + + verify(repository).save(entity) + assertEquals(entity, found) + } + + // delete() + + @Test + open fun `delete() deletes in the repository`() { + service.delete(entity) + + verify(repository).delete(entity) } } abstract class AbstractModelServiceTest, R : JpaRepository> : AbstractServiceTest() { - @Nested - inner class ExistsById { - @Test - fun `returns true when an entity with the given id exists in the repository`() { - whenever(repository.existsById(entity.id!!)).doReturn(true) - val found = service.existsById(entity.id!!) + // existsById() - assertTrue(found) - } + @Test + open fun `existsById() returns true when an entity with the given id exists in the repository`() { + whenever(repository.existsById(entity.id!!)).doReturn(true) - @Test - fun `returns false when no entity with the given id exists in the repository`() { - whenever(repository.existsById(entity.id!!)).doReturn(false) + val found = service.existsById(entity.id!!) - val found = service.existsById(entity.id!!) - - assertFalse(found) - } + assertTrue(found) } - @Nested - inner class GetById { - @Test - fun `returns the entity with the given id from the repository`() { - whenever(repository.findById(entity.id!!)).doReturn(Optional.of(entity)) + @Test + open fun `existsById() returns false when no entity with the given id exists in the repository`() { + whenever(repository.existsById(entity.id!!)).doReturn(false) - val found = service.getById(entity.id!!) + val found = service.existsById(entity.id!!) - assertEquals(entity, found) - } - - @Test - fun `throws EntityNotFoundRestException when no entity with the given id exists in the repository`() { - whenever(repository.findById(entity.id!!)).doReturn(Optional.empty()) - - val exception = assertThrows { service.getById(entity.id!!) } - assertTrue(exception.value is Long) - assertEquals(entity.id, exception.value as Long) - } + assertFalse(found) } - @Nested - inner class SaveModel { - @Test - fun `throws EntityAlreadyExistsRestException when an entity with the given id exists in the repository`() { - doReturn(true).whenever(repository).existsById(entity.id!!) + // getById() - val exception = assertThrows { service.save(entity) } - assertTrue(exception.value is Long) - assertEquals(entity.id, exception.value as Long) - } + @Test + open fun `getById() returns the entity with the given id from the repository`() { + whenever(repository.findById(entity.id!!)).doReturn(Optional.of(entity)) + + val found = service.getById(entity.id!!) + + assertEquals(entity, found) } - @Nested - inner class Update { - @Test - fun `calls and returns save() in the repository`() { - whenever(repository.save(entity)).doReturn(entity) - doReturn(true).whenever(service).existsById(entity.id!!) - doReturn(entity).whenever(service).getById(entity.id!!) + @Test + open fun `getById() throws EntityNotFoundRestException when no entity with the given id exists in the repository`() { + whenever(repository.findById(entity.id!!)).doReturn(Optional.empty()) - val found = service.update(entity) - - verify(repository).save(entity) - assertEquals(entity, found) - } - - @Test - fun `throws EntityNotFoundRestException when no entity with the given id exists in the repository`() { - doReturn(false).whenever(service).existsById(entity.id!!) - - val exception = assertThrows { service.update(entity) } - assertTrue(exception.value is Long) - assertEquals(entity.id, exception.value as Long) - } + val exception = assertThrows { service.getById(entity.id!!) } + assertTrue(exception.value is Long) + assertEquals(entity.id, exception.value as Long) } - @Nested - inner class DeleteById { - @Test - fun `calls deleteById() in the repository with the given id`() { - doReturn(entity).whenever(service).getById(entity.id!!) + // save() - service.deleteById(entity.id!!) + @Test + open fun `save() throws EntityAlreadyExistsRestException when an entity with the given id exists in the repository`() { + doReturn(true).whenever(repository).existsById(entity.id!!) - verify(repository).delete(entity) - } + val exception = assertThrows { service.save(entity) } + assertTrue(exception.value is Long) + assertEquals(entity.id, exception.value as Long) + } + + // update() + + @Test + override fun `update() saves in the repository and returns the updated value`() { + whenever(repository.save(entity)).doReturn(entity) + doReturn(true).whenever(service).existsById(entity.id!!) + doReturn(entity).whenever(service).getById(entity.id!!) + + val found = service.update(entity) + + verify(repository).save(entity) + assertEquals(entity, found) + } + + @Test + open fun `update() throws EntityNotFoundRestException when no entity with the given id exists in the repository`() { + doReturn(false).whenever(service).existsById(entity.id!!) + + val exception = assertThrows { service.update(entity) } + assertTrue(exception.value is Long) + assertEquals(entity.id, exception.value as Long) + } + + // deleteById() + + @Test + open fun `deleteById() deletes the entity with the given id in the repository`() { + doReturn(entity).whenever(service).getById(entity.id!!) + + service.deleteById(entity.id!!) + + verify(repository).delete(entity) } } @@ -194,101 +185,97 @@ abstract class AbstractNamedModelServiceTest() { protected abstract val entityWithEntityName: E - @Nested - inner class ExistsByName { - @Test - fun `returns true when an entity with the given name exists`() { - whenever(repository.existsByName(entity.name)).doReturn(true) + // existsByName() - val found = service.existsByName(entity.name) + @Test + open fun `existsByName() returns true when an entity with the given name exists`() { + whenever(repository.existsByName(entity.name)).doReturn(true) - assertTrue(found) - } + val found = service.existsByName(entity.name) - @Test - fun `returns false when no entity with the given name exists`() { - whenever(repository.existsByName(entity.name)).doReturn(false) - - val found = service.existsByName(entity.name) - - assertFalse(found) - } + assertTrue(found) } - @Nested - inner class GetByName { - @Test - fun `returns the entity with the given name`() { - whenever(repository.findByName(entity.name)).doReturn(entity) + @Test + open fun `existsByName() returns false when no entity with the given name exists`() { + whenever(repository.existsByName(entity.name)).doReturn(false) - val found = service.getByName(entity.name) + val found = service.existsByName(entity.name) - assertEquals(entity, found) - } - - @Test - fun `throws EntityNotFoundRestException when no entity with the given name exists`() { - whenever(repository.findByName(entity.name)).doReturn(null) - - val exception = assertThrows { service.getByName(entity.name) } - assertEquals(entity.name, exception.value) - } + assertFalse(found) } - @Nested - inner class SaveNamedModel { - @Test - fun `throws EntityAlreadyExistsRestException when an entity with the given name exists`() { - doReturn(true).whenever(service).existsByName(entity.name) + // getByName() - val exception = assertThrows { service.save(entity) } - assertEquals(entity.name, exception.value) - } + @Test + open fun `getByName() returns the entity with the given name`() { + whenever(repository.findByName(entity.name)).doReturn(entity) + + val found = service.getByName(entity.name) + + assertEquals(entity, found) } - @Nested - inner class Update { - @Test - fun `calls and returns save() in the repository`() { - whenever(repository.save(entity)).doReturn(entity) - whenever(repository.findByName(entity.name)).doReturn(null) - doReturn(true).whenever(service).existsById(entity.id!!) - doReturn(entity).whenever(service).getById(entity.id!!) + @Test + open fun `getByName() throws EntityNotFoundRestException when no entity with the given name exists`() { + whenever(repository.findByName(entity.name)).doReturn(null) - val found = service.update(entity) - - verify(repository).save(entity) - assertEquals(entity, found) - } - - @Test - fun `throws EntityNotFoundRestException when no entity with the given id exists in the repository`() { - whenever(repository.findByName(entity.name)).doReturn(null) - doReturn(false).whenever(service).existsById(entity.id!!) - - val exception = assertThrows { service.update(entity) } - assertTrue(exception.value is Long) - assertEquals(entity.id, exception.value as Long) - } - - @Test - fun `throws EntityAlreadyExistsRestException when an entity with the updated name exists`() { - whenever(repository.findByName(entity.name)).doReturn(entityWithEntityName) - doReturn(entity).whenever(service).getById(entity.id!!) - - val exception = assertThrows { service.update(entity) } - assertEquals(entity.name, exception.value) - } + val exception = assertThrows { service.getByName(entity.name) } + assertEquals(entity.name, exception.value) } - @Nested - inner class DeleteByName { - @Test - fun `calls deleteByName() in the repository with the given name`() { - service.deleteByName(entity.name) + // save() - verify(repository).deleteByName(entity.name) - } + @Test + open fun `save() throws EntityAlreadyExistsRestException when an entity with the given name exists`() { + doReturn(true).whenever(service).existsByName(entity.name) + + val exception = assertThrows { service.save(entity) } + assertEquals(entity.name, exception.value) + } + + // update() + + @Test + override fun `update() saves in the repository and returns the updated value`() { + whenever(repository.save(entity)).doReturn(entity) + whenever(repository.findByName(entity.name)).doReturn(null) + doReturn(true).whenever(service).existsById(entity.id!!) + doReturn(entity).whenever(service).getById(entity.id!!) + + val found = service.update(entity) + + verify(repository).save(entity) + assertEquals(entity, found) + } + + @Test + override fun `update() throws EntityNotFoundRestException when no entity with the given id exists in the repository`() { + whenever(repository.findByName(entity.name)).doReturn(null) + doReturn(false).whenever(service).existsById(entity.id!!) + + val exception = assertThrows { service.update(entity) } + assertTrue(exception.value is Long) + assertEquals(entity.id, exception.value as Long) + + } + + @Test + open fun `update() throws EntityAlreadyExistsRestException when an entity with the updated name exists`() { + whenever(repository.findByName(entity.name)).doReturn(entityWithEntityName) + doReturn(entity).whenever(service).getById(entity.id!!) + + val exception = assertThrows { service.update(entity) } + assertEquals(entity.name, exception.value) + } + + // deleteByName() + + @Test + open fun `deleteByName() deletes the entity with the given name in the repository`() { + service.deleteByName(entity.name) + + verify(repository).deleteByName(entity.name) } } @@ -305,17 +292,17 @@ abstract class AbstractExternalModelServiceTest, U : super.afterEach() } - @Nested - inner class SaveDto { - @Test - fun `calls and returns save() with the created entity`() = saveDtoTest(entity, entitySaveDto, service) - } + // save() - @Nested - inner class UpdateDto { - @Test - fun `calls and returns update() with the created entity`() = updateDtoTest(entity, entityUpdateDto, service) - } + @Test + open fun `save(dto) calls and returns save() with the created entity`() = + saveDtoTest(entity, entitySaveDto, service) + + // update() + + @Test + open fun `update(dto) calls and returns update() with the created entity`() = + updateDtoTest(entity, entityUpdateDto, service) } abstract class AbstractExternalNamedModelServiceTest, U : EntityDto, S : ExternalNamedModelService, R : NamedJpaRepository> : @@ -329,17 +316,17 @@ abstract class AbstractExternalNamedModelServiceTest> saveDtoTest(entity: E, entitySaveDto: N, service: ExternalService) { diff --git a/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/AccountsServiceTest.kt b/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/AccountsServiceTest.kt index 1fc7d60..da872a2 100644 --- a/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/AccountsServiceTest.kt +++ b/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/AccountsServiceTest.kt @@ -19,7 +19,8 @@ import javax.servlet.http.Cookie import javax.servlet.http.HttpServletRequest import kotlin.test.* -class EmployeeServiceTest : AbstractExternalModelServiceTest() { +class EmployeeServiceTest : + AbstractExternalModelServiceTest() { private val passwordEncoder = BCryptPasswordEncoder() override val entity: Employee = employee(passwordEncoder, id = 0L) @@ -33,7 +34,16 @@ class EmployeeServiceTest : AbstractExternalModelServiceTest { service.getById(entityDefaultGroupUser.id, ignoreDefaultGroupUsers = true, ignoreSystemUsers = false) } - assertTrue(exception.value is Long) - assertEquals(entityDefaultGroupUser.id, exception.value as Long) - } + val found = service.existsByFirstNameAndLastName(entity.firstName, entity.lastName) - @Test - fun `throws EntityNotFoundRestException when the corresponding employee is a system user`() { - whenever(repository.findById(entitySystemUser.id)).doReturn(Optional.of(entitySystemUser)) - - val exception = assertThrows { service.getById(entitySystemUser.id, ignoreDefaultGroupUsers = false, ignoreSystemUsers = true) } - assertTrue(exception.value is Long) - assertEquals(entitySystemUser.id, exception.value as Long) - } + assertFalse(found) } - @Nested - inner class GetByGroup { - @Test - fun `returns all the employees with the given group from the repository`() { - whenever(repository.findAllByGroup(group)).doReturn(entityList) + // getById() - val found = service.getByGroup(group) + @Test + fun `getById() throws EntityNotFoundRestException when the corresponding employee is a default group user`() { + whenever(repository.findById(entityDefaultGroupUser.id)).doReturn(Optional.of(entityDefaultGroupUser)) - assertTrue(found.containsAll(entityList)) - assertTrue(entityList.containsAll(found)) - } - - @Test - fun `returns an empty list when there is no employee with the given group in the repository`() { - whenever(repository.findAllByGroup(group)).doReturn(listOf()) - - val found = service.getByGroup(group) - - assertTrue(found.isEmpty()) + val exception = assertThrows { + service.getById( + entityDefaultGroupUser.id, + ignoreDefaultGroupUsers = true, + ignoreSystemUsers = false + ) } + assertTrue(exception.value is Long) + assertEquals(entityDefaultGroupUser.id, exception.value as Long) } - @Nested - inner class GetDefaultGroupUser { - @Test - fun `returns the default employee of the given group from the repository`() { - whenever(repository.findByIsDefaultGroupUserIsTrueAndGroupIs(group)).doReturn(entityDefaultGroupUser) + @Test + fun `getById() throws EntityNotFoundRestException when the corresponding employee is a system user`() { + whenever(repository.findById(entitySystemUser.id)).doReturn(Optional.of(entitySystemUser)) - val found = service.getDefaultGroupEmployee(group) - - assertEquals(entityDefaultGroupUser, found) + val exception = assertThrows { + service.getById( + entitySystemUser.id, + ignoreDefaultGroupUsers = false, + ignoreSystemUsers = true + ) } + assertTrue(exception.value is Long) + assertEquals(entitySystemUser.id, exception.value as Long) } - @Nested - inner class Save { - @Test - fun `calls save() in the repository`() { - whenever(repository.save(entity)).doReturn(entity) - doReturn(false).whenever(repository).existsByFirstNameAndLastName(entity.firstName, entity.lastName) + // getByGroup() - val found = service.save(entity) + @Test + fun `getByGroup() returns all the employees with the given group from the repository`() { + whenever(repository.findAllByGroup(group)).doReturn(entityList) - verify(repository).save(entity) - assertEquals(entity, found) - } + val found = service.getByGroup(group) - @Test - fun `throws EntityAlreadyExistsException when firstName and lastName exists`() { - doReturn(true).whenever(repository).existsByFirstNameAndLastName(entity.firstName, entity.lastName) - - val exception = assertThrows { service.save(entity) } - assertEquals("${entity.firstName} ${entity.lastName}", exception.value) - } + assertTrue(found.containsAll(entityList)) + assertTrue(entityList.containsAll(found)) } - @Nested - inner class SaveDto { - @Test - fun `calls save() with the created employee`() { - whenever(entitySaveDto.toEntity()).doReturn(entitySaveDtoEmployee) - doReturn(entitySaveDtoEmployee).whenever(service).save(entitySaveDtoEmployee) + @Test + fun `getByGroup() returns an empty list when there is no employee with the given group in the repository`() { + whenever(repository.findAllByGroup(group)).doReturn(listOf()) - val found = service.save(entitySaveDto) + val found = service.getByGroup(group) - verify(service).save(entitySaveDtoEmployee) - assertEquals(entitySaveDtoEmployee, found) - } + assertTrue(found.isEmpty()) } - @Nested - inner class Update { - @Test - fun `throws EntityAlreadyExistsRestException when a different employee with the given first name and last name exists`() { - whenever(repository.findByFirstNameAndLastName(entity.firstName, entity.lastName)).doReturn(entityDefaultGroupUser) - doReturn(entity).whenever(service).getById(eq(entity.id), any(), any()) + // getDefaultGroupUser() - val exception = assertThrows { service.update(entity, true, ignoreSystemUsers = true) } - assertTrue(exception.value is String) - assertEquals("${entity.firstName} ${entity.lastName}", exception.value as String) + @Test + fun `getDefaultGroupUser() returns the default employee of the given group from the repository`() { + whenever(repository.findByIsDefaultGroupUserIsTrueAndGroupIs(group)).doReturn(entityDefaultGroupUser) + + val found = service.getDefaultGroupEmployee(group) + + assertEquals(entityDefaultGroupUser, found) + } + + // save() + + override fun `save() saves in the repository and returns the saved value`() { + whenever(repository.save(entity)).doReturn(entity) + doReturn(false).whenever(repository).existsByFirstNameAndLastName(entity.firstName, entity.lastName) + + val found = service.save(entity) + + verify(repository).save(entity) + assertEquals(entity, found) + } + + @Test + fun `save() throws EntityAlreadyExistsException when firstName and lastName exists`() { + doReturn(true).whenever(repository).existsByFirstNameAndLastName(entity.firstName, entity.lastName) + + val exception = assertThrows { service.save(entity) } + assertEquals("${entity.firstName} ${entity.lastName}", exception.value) + } + + + @Test + fun `save(dto) calls and returns save() with the created employee`() { + whenever(entitySaveDto.toEntity()).doReturn(entitySaveDtoEmployee) + doReturn(entitySaveDtoEmployee).whenever(service).save(entitySaveDtoEmployee) + + val found = service.save(entitySaveDto) + + verify(service).save(entitySaveDtoEmployee) + assertEquals(entitySaveDtoEmployee, found) + } + + // update() + + @Test + fun `update() throws EntityAlreadyExistsRestException when a different employee with the given first name and last name exists`() { + whenever(repository.findByFirstNameAndLastName(entity.firstName, entity.lastName)).doReturn( + entityDefaultGroupUser + ) + doReturn(entity).whenever(service).getById(eq(entity.id), any(), any()) + + val exception = assertThrows { + service.update( + entity, + true, + ignoreSystemUsers = true + ) } + assertTrue(exception.value is String) + assertEquals("${entity.firstName} ${entity.lastName}", exception.value as String) } } -class EmployeeGroupServiceTest : AbstractExternalModelServiceTest() { +class EmployeeGroupServiceTest : + AbstractExternalNamedModelServiceTest() { private val employeeService: EmployeeService = mock() override val repository: EmployeeGroupRepository = mock() - override val service: EmployeeGroupServiceImpl = spy(EmployeeGroupServiceImpl(repository, employeeService)) + override val service: EmployeeGroupServiceImpl = spy(EmployeeGroupServiceImpl(employeeService, repository)) override val entity: EmployeeGroup = employeeGroup(id = 0L, name = "group") override val anotherEntity: EmployeeGroup = employeeGroup(id = 1L, name = "another group") override val entitySaveDto: EmployeeGroupSaveDto = spy(employeeGroupSaveDto(name = "group")) override val entityUpdateDto: EmployeeGroupUpdateDto = spy(employeeGroupUpdateDto(id = 0L, name = "groupL")) + override val entityWithEntityName: EmployeeGroup = employeeGroup(id = 2L, name = entity.name) private val groupEmployeeId = 1000000L + entity.id!! private val groupEmployee = employee(BCryptPasswordEncoder(), id = groupEmployeeId, group = entity) @@ -186,213 +209,188 @@ class EmployeeGroupServiceTest : AbstractExternalModelServiceTest = arrayOf(Cookie(defaultGroupCookieName, groupEmployeeId.toString())) - val request: HttpServletRequest = mock() + // getRequestDefaultGroup() - whenever(request.cookies).doReturn(cookies) - whenever(employeeService.getById(eq(groupEmployeeId), any(), any())).doReturn(groupEmployee) + @Test + fun `getRequestDefaultGroup() returns the group contained in the cookie of the HTTP request`() { + val cookies: Array = arrayOf(Cookie(defaultGroupCookieName, groupEmployeeId.toString())) + val request: HttpServletRequest = mock() - val found = service.getRequestDefaultGroup(request) + whenever(request.cookies).doReturn(cookies) + whenever(employeeService.getById(eq(groupEmployeeId), any(), any())).doReturn(groupEmployee) - assertEquals(entity, found) - } + val found = service.getRequestDefaultGroup(request) - @Test - fun `throws EntityNotFoundRestException when the HTTP request does not contains a cookie for the default group`() { - val request: HttpServletRequest = mock() - - whenever(request.cookies).doReturn(arrayOf()) - - val exception = assertThrows { service.getRequestDefaultGroup(request) } - assertEquals("defaultGroup", exception.value) - } + assertEquals(entity, found) } - @Nested - inner class SetResponseDefaultGroup { - @Test - fun `the default group cookie has been added to the given HTTP response with the given group id`() { - val response = MockHttpServletResponse() + @Test + fun `getRequestDefaultGroup() throws EntityNotFoundRestException when the HTTP request does not contains a cookie for the default group`() { + val request: HttpServletRequest = mock() - whenever(employeeService.getDefaultGroupEmployee(entity)).doReturn(groupEmployee) - doReturn(entity).whenever(service).getById(entity.id!!) + whenever(request.cookies).doReturn(arrayOf()) - service.setResponseDefaultGroup(entity.id!!, response) - val found = response.getCookie(defaultGroupCookieName) - - assertNotNull(found) - assertEquals(defaultGroupCookieName, found.name) - assertEquals(groupEmployeeId.toString(), found.value) - assertEquals(defaultGroupCookieMaxAge, found.maxAge) - assertTrue(found.isHttpOnly) - assertTrue(found.secure) - } + val exception = assertThrows { service.getRequestDefaultGroup(request) } + assertEquals("defaultGroup", exception.value) } - @Nested - inner class AddEmployeeToGroup { - @Test - fun `calls addEmployeeToGroup() with the group of the given groupId and the employee of the given employeeId`() { - whenever(employeeService.getById(groupEmployeeId)).doReturn(groupEmployee) - doReturn(entity).whenever(service).getById(entity.id!!) + // setResponseDefaultGroup() - service.addEmployeeToGroup(entity.id!!, groupEmployeeId) + @Test + fun `setResponseDefaultGroup() the default group cookie has been added to the given HTTP response with the given group id`() { + val response = MockHttpServletResponse() - verify(service).addEmployeeToGroup(entity, groupEmployee) - } + whenever(employeeService.getDefaultGroupEmployee(entity)).doReturn(groupEmployee) + doReturn(entity).whenever(service).getById(entity.id!!) - @Test - fun `calls update() and employeeService_update() with the updated entities`() { - val group = employeeGroup() - val employee = employee() + service.setResponseDefaultGroup(entity.id!!, response) + val found = response.getCookie(defaultGroupCookieName) - whenever(employeeService.update(employee)).doReturn(employee) - doReturn(group).whenever(service).update(group) - - service.addEmployeeToGroup(group, employee) - - verify(service).update(group) - verify(employeeService).update(employee) - - assertTrue(group.employees.contains(employee)) - assertEquals(group, employee.group) - } - - @Test - fun `do nothing when the given employee is already in the given group`() { - val group = employeeGroup() - val employee = employee(group = group) - - service.addEmployeeToGroup(group, employee) - - verify(service, times(0)).update(group) - verify(employeeService, times(0)).update(employee) - } - - @Test - fun `remove previous group from the given employee and add it the the given group`() { - val group = employeeGroup(id = 0L) - val previousGroup = employeeGroup(id = 1L) - val employee = employee(group = previousGroup) - - whenever(employeeService.update(employee)).doReturn(employee) - doReturn(group).whenever(service).update(group) - doReturn(group).whenever(service).update(previousGroup) - - service.addEmployeeToGroup(group, employee) - - verify(service).removeEmployeeFromGroup(previousGroup, employee) - verify(service).update(group) - verify(employeeService, times(2)).update(employee) - - assertTrue(group.employees.contains(employee)) - assertEquals(group, employee.group) - } + assertNotNull(found) + assertEquals(defaultGroupCookieName, found.name) + assertEquals(groupEmployeeId.toString(), found.value) + assertEquals(defaultGroupCookieMaxAge, found.maxAge) + assertTrue(found.isHttpOnly) + assertTrue(found.secure) } - @Nested - inner class RemoveEmployeeFromGroup { - @Test - fun `calls removeEmployeeFromGroup() with the group of the given group id and the employee of the given employee id`() { - whenever(employeeService.getById(groupEmployeeId)).doReturn(groupEmployee) - doReturn(entity).whenever(service).getById(entity.id!!) - doAnswer { it.arguments[0] }.whenever(service).update(any()) + // addEmployeeToGroup() - service.removeEmployeeFromGroup(entity.id!!, groupEmployeeId) + @Test + fun `addEmployeeToGroup() calls addEmployeeToGroup() with the group of the given groupId and the employee of the given employeeId`() { + whenever(employeeService.getById(groupEmployeeId)).doReturn(groupEmployee) + doReturn(entity).whenever(service).getById(entity.id!!) + doAnswer { }.whenever(service).addEmployeeToGroup(entity, groupEmployee) - verify(service).removeEmployeeFromGroup(entity, groupEmployee) - } + service.addEmployeeToGroup(entity.id!!, groupEmployeeId) - @Test - fun `calls update() and employeeService_update() with the updated entities`() { - val employee = employee() - val group = employeeGroup(employees = mutableSetOf(employee)) - employee.group = group + verify(service).addEmployeeToGroup(entity, groupEmployee) + } - whenever(employeeService.update(employee)).doReturn(employee) - doReturn(group).whenever(service).update(group) + @Test + fun `addEmployeeToGroup() calls update() and employeeService_update() with the updated entities`() { + val group = employeeGroup() + val employee = employee() - service.removeEmployeeFromGroup(group, employee) + whenever(employeeService.update(employee)).doReturn(employee) + doReturn(group).whenever(service).update(group) - verify(service).update(group) - verify(employeeService).update(employee) + service.addEmployeeToGroup(group, employee) - assertFalse(group.employees.contains(employee)) - assertNull(employee.group) - } + verify(service).update(group) + verify(employeeService).update(employee) - @Test - fun `do nothing when the given employee is not in the given group`() { - val employee = employee() - val group = employeeGroup(id = 0L) - val anotherGroup = employeeGroup(id = 1L, employees = mutableSetOf(employee)) - employee.group = anotherGroup + assertTrue(group.employees.contains(employee)) + assertEquals(group, employee.group) + } - service.removeEmployeeFromGroup(group, employee) + @Test + fun `addEmployeeToGroup() do nothing when the given employee is already in the given group`() { + val group = employeeGroup() + val employee = employee(group = group) - verify(service, times(0)).update(anotherGroup) - verify(employeeService, times(0)).update(employee) - } + service.addEmployeeToGroup(group, employee) - @Test - fun `do nothing when the given employee is not in a group`() { - val employee = employee() - val group = employeeGroup() + verify(service, times(0)).update(group) + verify(employeeService, times(0)).update(employee) + } - service.removeEmployeeFromGroup(group, employee) + @Test + fun `addEmployeeToGroup() remove previous group from the given employee and add it the the given group`() { + val group = employeeGroup(id = 0L) + val previousGroup = employeeGroup(id = 1L) + val employee = employee(group = previousGroup) - verify(service, times(0)).update(group) - verify(employeeService, times(0)).update(employee) - } + whenever(employeeService.update(employee)).doReturn(employee) + doReturn(group).whenever(service).update(group) + doReturn(group).whenever(service).update(previousGroup) + + service.addEmployeeToGroup(group, employee) + + verify(service).removeEmployeeFromGroup(previousGroup, employee) + verify(service).update(group) + verify(employeeService, times(2)).update(employee) + + assertTrue(group.employees.contains(employee)) + assertEquals(group, employee.group) + } + + // removeEmployeeFromGroup() + + @Test + fun `removeEmployeeFromGroup() calls removeEmployeeFromGroup() with the group of the given group id and the employee of the given employee id`() { + whenever(employeeService.getById(groupEmployeeId)).doReturn(groupEmployee) + doReturn(entity).whenever(service).getById(entity.id!!) + doAnswer { it.arguments[0] }.whenever(service).update(any()) + + service.removeEmployeeFromGroup(entity.id!!, groupEmployeeId) + + verify(service).removeEmployeeFromGroup(entity, groupEmployee) + } + + @Test + fun `removeEmployeeFromGroup() calls update() and employeeService_update() with the updated entities`() { + val employee = employee() + val group = employeeGroup(employees = mutableSetOf(employee)) + employee.group = group + + whenever(employeeService.update(employee)).doReturn(employee) + doReturn(group).whenever(service).update(group) + + service.removeEmployeeFromGroup(group, employee) + + verify(service).update(group) + verify(employeeService).update(employee) + + assertFalse(group.employees.contains(employee)) + assertNull(employee.group) + } + + @Test + fun `removeEmployeeFromGroup() do nothing when the given employee is not in the given group`() { + val employee = employee() + val group = employeeGroup(id = 0L) + val anotherGroup = employeeGroup(id = 1L, employees = mutableSetOf(employee)) + employee.group = anotherGroup + + service.removeEmployeeFromGroup(group, employee) + + verify(service, times(0)).update(anotherGroup) + verify(employeeService, times(0)).update(employee) + } + + @Test + fun `removeEmployeeFromGroup() do nothing when the given employee is not in a group`() { + val employee = employee() + val group = employeeGroup() + + service.removeEmployeeFromGroup(group, employee) + + verify(service, times(0)).update(group) + verify(employeeService, times(0)).update(employee) } } @@ -407,36 +405,39 @@ class EmployeeUserDetailsServiceTest { reset(employeeService, service) } - @Nested - inner class LoadUserByUsername { - @Test - fun `calls loadUserByEmployeeId() with the given username as an id`() { - whenever(employeeService.getById(eq(employee.id), any(), any())).doReturn(employee) - doReturn(User(employee.id.toString(), employee.password, listOf())).whenever(service).loadUserByEmployeeId(employee.id) + // loadUserByUsername() - service.loadUserByUsername(employee.id.toString()) + @Test + fun `loadUserByUsername() calls loadUserByEmployeeId() with the given username as an id`() { + whenever(employeeService.getById(eq(employee.id), any(), any())).doReturn(employee) + doReturn(User(employee.id.toString(), employee.password, listOf())).whenever(service) + .loadUserByEmployeeId(employee.id) - verify(service).loadUserByEmployeeId(eq(employee.id), any()) - } + service.loadUserByUsername(employee.id.toString()) - @Test - fun `throws UsernameNotFoundException when no employee with the given id exists`() { - whenever(employeeService.getById(eq(employee.id), any(), any())).doThrow(EntityNotFoundRestException(employee.id)) - - assertThrows { service.loadUserByUsername(employee.id.toString()) } - } + verify(service).loadUserByEmployeeId(eq(employee.id), any()) } - @Nested - inner class LoadUserByEmployeeId { - @Test - fun `returns an User corresponding to the employee with the given id`() { - whenever(employeeService.getById(eq(employee.id), any(), any())).doReturn(employee) + @Test + fun `loadUserByUsername() throws UsernameNotFoundException when no employee with the given id exists`() { + whenever(employeeService.getById(eq(employee.id), any(), any())).doThrow( + EntityNotFoundRestException( + employee.id + ) + ) - val found = service.loadUserByEmployeeId(employee.id) + assertThrows { service.loadUserByUsername(employee.id.toString()) } + } - assertEquals(employee.id, found.username.toLong()) - assertEquals(employee.password, found.password) - } + // loadUserByEmployeeId + + @Test + fun `loadUserByEmployeeId() returns an User corresponding to the employee with the given id`() { + whenever(employeeService.getById(eq(employee.id), any(), any())).doReturn(employee) + + val found = service.loadUserByEmployeeId(employee.id) + + assertEquals(employee.id, found.username.toLong()) + assertEquals(employee.password, found.password) } } diff --git a/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/CompanyServiceTest.kt b/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/CompanyServiceTest.kt index bd2a7d1..450336a 100644 --- a/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/CompanyServiceTest.kt +++ b/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/CompanyServiceTest.kt @@ -9,7 +9,8 @@ import org.junit.jupiter.api.Nested import kotlin.test.assertFalse import kotlin.test.assertTrue -class CompanyServiceTest : AbstractExternalNamedModelServiceTest() { +class CompanyServiceTest : + AbstractExternalNamedModelServiceTest() { private val recipeService: RecipeJavaService = mock() override val repository: CompanyRepository = mock() override val service: CompanyService = spy(CompanyServiceImpl(repository, recipeService)) @@ -26,22 +27,21 @@ class CompanyServiceTest : AbstractExternalNamedModelServiceTest { service.save(entity) } - assertEquals(entity.name, exception.value) - } + val found = service.hasSimdut(entity.id!!) + + assertTrue(found) } - @Nested - inner class SaveDto { - @Test - fun `calls simdutService_write() with the saved entity`() { - val mockMultipartFile = spy(MockMultipartFile("simdut", byteArrayOf())) - val materialSaveDto = spy(materialSaveDto(simdutFile = mockMultipartFile)) + // getAllNotMixType() - doReturn(false).whenever(mockMultipartFile).isEmpty - doReturn(entity).whenever(materialSaveDto).toEntity() - doReturn(entity).whenever(service).save(entity) + @Test + fun `getAllNotMixType() returns a list containing every material that are not a mix type`() { + val mixTypeMaterial = material(name = "mix type material", isMixType = true) + val materialList = listOf(entity, mixTypeMaterial) - service.save(materialSaveDto) + doReturn(materialList).whenever(service).getAll() - verify(simdutService).write(entity, mockMultipartFile) - } + val found = service.getAllNotMixType() + + assertTrue(found.contains(entity)) + assertFalse(found.contains(mixTypeMaterial)) } - @Nested - inner class Update { - @Test - fun `throws EntityAlreadyExistsRestException when another material with the updated name exists in the repository`() { - val material = material(id = 0L, name = "name") - val anotherMaterial = material(id = 1L, name = "name") + // save() - whenever(repository.findByName(material.name)).doReturn(anotherMaterial) - doReturn(entity).whenever(service).getById(material.id!!) + @Test + fun `save() throws EntityAlreadyExistsRestException when a material with the given name exists in the repository`() { + doReturn(true).whenever(service).existsByName(entity.name) - val exception = assertThrows { service.update(material) } - assertEquals(material.name, exception.value) - } + val exception = assertThrows { service.save(entity) } + assertEquals(entity.name, exception.value) } - /** Helper function to replace collections.in because the id is not considered in the equals function of Material while Thymeleaf is supported. */ - private infix fun Collection.contains(material: Material): Boolean = - any { it.id == material.id } + @Test + fun `save(dto) calls simdutService_write() with the saved entity`() { + val mockMultipartFile = spy(MockMultipartFile("simdut", byteArrayOf())) + val materialSaveDto = spy(materialSaveDto(simdutFile = mockMultipartFile)) - @Nested - inner class GetAllForMixCreation { - @Test - fun `returns all normal materials and all mix type materials for the given recipe`() { - val normalMaterial = material(id = 0L, isMixType = false) - val mixTypeMaterial = material(id = 1L, isMixType = true) - val anotherMixTypeMaterial = material(id = 2L, isMixType = true) - val materials = listOf(normalMaterial, mixTypeMaterial, anotherMixTypeMaterial) - val recipe = - recipe(id = 0L, mixes = mutableListOf(mix(mixType = mixType(id = 0L, material = mixTypeMaterial)))) + doReturn(false).whenever(mockMultipartFile).isEmpty + doReturn(entity).whenever(materialSaveDto).toEntity() + doReturn(entity).whenever(service).save(entity) - whenever(recipeService.getById(recipe.id!!)).doReturn(recipe) - doReturn(materials).whenever(service).getAll() + service.save(materialSaveDto) - val found = service.getAllForMixCreation(recipe.id!!) - - assertTrue(found contains normalMaterial) - assertTrue(found contains mixTypeMaterial) - assertFalse(found contains anotherMixTypeMaterial) - } + verify(simdutService).write(entity, mockMultipartFile) } - @Nested - inner class GetAllForMixUpdate { - @Test - fun `returns all normal materials and all mix type materials for the recipe of the given mix without the mix type of the said mix`() { - val normalMaterial = material(id = 0L, isMixType = false) - val mixTypeMaterial = material(id = 1L, isMixType = true) - val anotherMixTypeMaterial = material(id = 2L, isMixType = true) - val materials = listOf(normalMaterial, mixTypeMaterial, anotherMixTypeMaterial) - val recipe = recipe(id = 0L, mixes = mutableListOf(mix(mixType = mixType(material = mixTypeMaterial)))) - val mix = mix(id = 1L, recipe = recipe, mixType = mixType(material = anotherMixTypeMaterial)) - recipe.mixes.add(mix) + // update() - whenever(mixService.getById(mix.id!!)).doReturn(mix) - doReturn(materials).whenever(service).getAll() + @Test + fun `update() throws EntityAlreadyExistsRestException when another material with the updated name exists in the repository`() { + val material = material(id = 0L, name = "name") + val anotherMaterial = material(id = 1L, name = "name") - val found = service.getAllForMixUpdate(mix.id!!) + whenever(repository.findByName(material.name)).doReturn(anotherMaterial) + doReturn(entity).whenever(service).getById(material.id!!) - assertTrue(found contains normalMaterial) - assertTrue(found contains mixTypeMaterial) - assertFalse(found contains anotherMixTypeMaterial) - } + val exception = assertThrows { service.update(material) } + assertEquals(material.name, exception.value) + } + + // getAllForMixCreation() + + @Test + fun `getAllForMixCreation() returns all normal materials and all mix type materials for the given recipe`() { + val normalMaterial = material(id = 0L, isMixType = false) + val mixTypeMaterial = material(id = 1L, isMixType = true) + val anotherMixTypeMaterial = material(id = 2L, isMixType = true) + val materials = listOf(normalMaterial, mixTypeMaterial, anotherMixTypeMaterial) + val recipe = + recipe(id = 0L, mixes = mutableListOf(mix(mixType = mixType(id = 0L, material = mixTypeMaterial)))) + + whenever(recipeService.getById(recipe.id!!)).doReturn(recipe) + doReturn(materials).whenever(service).getAll() + + val found = service.getAllForMixCreation(recipe.id!!) + + assertTrue(found contains normalMaterial) + assertTrue(found contains mixTypeMaterial) + assertFalse(found contains anotherMixTypeMaterial) + } + + // getAllForMixUpdate() + + @Test + fun `getAllForMixUpdate() returns all normal materials and all mix type materials for the recipe of the given mix without the mix type of the said mix`() { + val normalMaterial = material(id = 0L, isMixType = false) + val mixTypeMaterial = material(id = 1L, isMixType = true) + val anotherMixTypeMaterial = material(id = 2L, isMixType = true) + val materials = listOf(normalMaterial, mixTypeMaterial, anotherMixTypeMaterial) + val recipe = recipe(id = 0L, mixes = mutableListOf(mix(mixType = mixType(material = mixTypeMaterial)))) + val mix = mix(id = 1L, recipe = recipe, mixType = mixType(material = anotherMixTypeMaterial)) + recipe.mixes.add(mix) + + whenever(mixService.getById(mix.id!!)).doReturn(mix) + doReturn(materials).whenever(service).getAll() + + val found = service.getAllForMixUpdate(mix.id!!) + + assertTrue(found contains normalMaterial) + assertTrue(found contains mixTypeMaterial) + assertFalse(found contains anotherMixTypeMaterial) } // @Nested @@ -204,4 +190,8 @@ class MaterialServiceTest : // verify(simdutService).update(mockSimdutFile, entity) // } // } + + /** Helper function to replace collections.in because the id is not considered in the equals function of Material while Thymeleaf is supported. */ + private infix fun Collection.contains(material: Material): Boolean = + any { it.id == material.id } } diff --git a/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MaterialTypeServiceTest.kt b/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MaterialTypeServiceTest.kt index 5eadefa..04e85a3 100644 --- a/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MaterialTypeServiceTest.kt +++ b/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MaterialTypeServiceTest.kt @@ -13,7 +13,8 @@ import kotlin.test.assertEquals import kotlin.test.assertFalse import kotlin.test.assertTrue -class MaterialTypeServiceTest : AbstractExternalNamedModelServiceTest() { +class MaterialTypeServiceTest : + AbstractExternalNamedModelServiceTest() { override val repository: MaterialTypeRepository = mock() private val materialService: MaterialService = mock() override val service: MaterialTypeService = spy(MaterialTypeServiceImpl(repository, materialService)) @@ -23,7 +24,8 @@ class MaterialTypeServiceTest : AbstractExternalNamedModelServiceTest { service.save(entity) } - assertEquals(entity.prefix, exception.value) - } + @Test + fun `getAllSystemTypes() returns all system types`() { + whenever(repository.findAllBySystemTypeIs(true)).doReturn(listOf(systemType, anotherSystemType)) + + val found = service.getAllSystemTypes() + + assertTrue(found.contains(systemType)) + assertTrue(found.contains(anotherSystemType)) } - @Nested - inner class Update { - @Test - fun `calls and returns save() in the repository`() { - whenever(repository.save(entity)).doReturn(entity) - whenever(repository.findByName(entity.name)).doReturn(null) - whenever(repository.findByPrefix(entity.prefix)).doReturn(null) - doReturn(true).whenever(service).existsById(entity.id!!) - doReturn(entity).whenever(service).getById(entity.id!!) + // getAllNonSystemTypes() - val found = service.update(entity) + @Test + fun `getAllNonSystemTypes() returns all non system types`() { + whenever(repository.findAllBySystemTypeIs(false)).doReturn(listOf(entity, anotherEntity)) - verify(repository).save(entity) - assertEquals(entity, found) - } + val found = service.getAllNonSystemType() - @Test - fun `throws EntityNotFoundRestException when no entity with the given id exists in the repository`() { - whenever(repository.findByName(entity.name)).doReturn(null) - whenever(repository.findByPrefix(entity.prefix)).doReturn(null) - doReturn(false).whenever(service).existsById(entity.id!!) - doReturn(null).whenever(service).getById(entity.id!!) - - val exception = assertThrows { service.update(entity) } - assertTrue(exception.value is Long) - assertEquals(entity.id, exception.value as Long) - } - - @Test - fun `throws EntityAlreadyExistsRestException when an entity with the updated name exists`() { - whenever(repository.findByName(entity.name)).doReturn(entityWithEntityName) - whenever(repository.findByPrefix(entity.prefix)).doReturn(null) - doReturn(true).whenever(service).existsById(entity.id!!) - doReturn(entity).whenever(service).getById(entity.id!!) - - val exception = assertThrows { service.update(entity) } - assertEquals(entity.name, exception.value) - } - - @Test - fun `throws EntityAlreadyExistsRestException when an entity with the updated prefix exists`() { - val anotherMaterialType = materialType(prefix = entity.prefix) - whenever(repository.findByPrefix(entity.prefix)).doReturn(anotherMaterialType) - doReturn(entity).whenever(service).getById(entity.id!!) - - val exception = assertThrows { service.update(entity) } - assertEquals(entity.prefix, exception.value) - } + assertTrue(found.contains(entity)) + assertTrue(found.contains(anotherEntity)) } - @Nested - inner class Delete { - @Test - fun `calls delete() in the repository`() { - doReturn(false).whenever(service).isUsedByMaterial(entity) + // saveMaterialType() - service.delete(entity) + @Test + fun `saveMaterialType() throws EntityAlreadyExistsRestException when a material type with the given prefix already exists`() { + doReturn(true).whenever(service).existsByPrefix(entity.prefix) - verify(repository).delete(entity) - } + val exception = assertThrows { service.save(entity) } + assertEquals(entity.prefix, exception.value) + } - @Test - fun `throws CannotDeleteUsedMaterialTypeRestException when the material type is in use`() { - doReturn(true).whenever(service).isUsedByMaterial(entity) + // update() - assertThrows { service.delete(entity) } - } + override fun `update() saves in the repository and returns the updated value`() { + whenever(repository.save(entity)).doReturn(entity) + whenever(repository.findByName(entity.name)).doReturn(null) + whenever(repository.findByPrefix(entity.prefix)).doReturn(null) + doReturn(true).whenever(service).existsById(entity.id!!) + doReturn(entity).whenever(service).getById(entity.id!!) + + val found = service.update(entity) + + verify(repository).save(entity) + assertEquals(entity, found) + } + + override fun `update() throws EntityNotFoundRestException when no entity with the given id exists in the repository`() { + whenever(repository.findByName(entity.name)).doReturn(null) + whenever(repository.findByPrefix(entity.prefix)).doReturn(null) + doReturn(false).whenever(service).existsById(entity.id!!) + doReturn(null).whenever(service).getById(entity.id!!) + + val exception = assertThrows { service.update(entity) } + assertTrue(exception.value is Long) + assertEquals(entity.id, exception.value as Long) + } + + override fun `update() throws EntityAlreadyExistsRestException when an entity with the updated name exists`() { + whenever(repository.findByName(entity.name)).doReturn(entityWithEntityName) + whenever(repository.findByPrefix(entity.prefix)).doReturn(null) + doReturn(true).whenever(service).existsById(entity.id!!) + doReturn(entity).whenever(service).getById(entity.id!!) + + val exception = assertThrows { service.update(entity) } + assertEquals(entity.name, exception.value) + } + + @Test + fun `update() throws EntityAlreadyExistsRestException when an entity with the updated prefix exists`() { + val anotherMaterialType = materialType(prefix = entity.prefix) + whenever(repository.findByPrefix(entity.prefix)).doReturn(anotherMaterialType) + doReturn(entity).whenever(service).getById(entity.id!!) + + val exception = assertThrows { service.update(entity) } + assertEquals(entity.prefix, exception.value) + } + + // delete() + + @Test + fun `delete() calls delete() in the repository`() { + doReturn(false).whenever(service).isUsedByMaterial(entity) + + service.delete(entity) + + verify(repository).delete(entity) + } + + @Test + fun `delete() throws CannotDeleteUsedMaterialTypeRestException when the material type is in use`() { + doReturn(true).whenever(service).isUsedByMaterial(entity) + + assertThrows { service.delete(entity) } } } diff --git a/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MixMaterialServiceTest.kt b/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MixMaterialServiceTest.kt index 1ccac5d..698a0b5 100644 --- a/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MixMaterialServiceTest.kt +++ b/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MixMaterialServiceTest.kt @@ -22,22 +22,21 @@ class MixMaterialServiceTest : AbstractModelServiceTest { service.getByMaterial(material) } - assertEquals(material.name, exception.value) - } + assertEquals(entity, found) } - @Nested - inner class SaveMixType { - @Test - fun `throws EntityAlreadyExistsRestException when a material with the name of the new mix type exists`() { - whenever(materialService.existsByName(entity.name)).doReturn(true) + @Test + fun `getByMaterial() throws EntityNotFoundRestException when no mix type with the given material exists`() { + whenever(repository.findByMaterial(material)).doReturn(null) - val exception = assertThrows { service.save(entity) } - assertEquals(entity.name, exception.value) - } + val exception = assertThrows { service.getByMaterial(material) } + assertEquals(material.name, exception.value) } - @Nested - inner class CreateForNameAndMaterialType { - @Test - fun `creates a save a valid mix type with the given name and material type`() { - val name = entity.name - val materialType = materialType() + // save() - doAnswer { it.arguments[0] }.whenever(service).save(any()) + @Test + fun `save() throws EntityAlreadyExistsRestException when a material with the name of the new mix type exists`() { + whenever(materialService.existsByName(entity.name)).doReturn(true) - val found = service.createForNameAndMaterialType(name, materialType) - - verify(service).save(any()) - - assertEquals(name, found.name) - assertEquals(name, found.material.name) - assertEquals(materialType, found.material.materialType) - assertTrue(found.material.isMixType) - } + val exception = assertThrows { service.save(entity) } + assertEquals(entity.name, exception.value) } - @Nested - inner class UpdateForNameAndMaterialType { - @Test - fun `updates the given mix type with the given name and material type`() { - val mixType = mixType(id = 1L, material = material(isMixType = true)) - val name = entity.name - val materialType = materialType() + // createForNameAndMaterialType() - doAnswer { it.arguments[0] }.whenever(service).update(any()) + @Test + fun `createForNameAndMaterialType() creates a save a valid mix type with the given name and material type`() { + val name = entity.name + val materialType = materialType() - val found = service.updateForNameAndMaterialType(mixType, name, materialType) + doAnswer { it.arguments[0] }.whenever(service).save(any()) - verify(service).update(any()) + val found = service.createForNameAndMaterialType(name, materialType) - assertEquals(mixType.id, found.id) - assertEquals(name, found.name) - assertEquals(name, found.material.name) - assertEquals(materialType, found.material.materialType) - assertTrue(found.material.isMixType) - } + verify(service).save(any()) + + assertEquals(name, found.name) + assertEquals(name, found.material.name) + assertEquals(materialType, found.material.materialType) + assertTrue(found.material.isMixType) + } + + // updateForNameAndMaterialType() + + @Test + fun `updateForNameAndMaterialType() updates the given mix type with the given name and material type`() { + val mixType = mixType(id = 1L, material = material(isMixType = true)) + val name = entity.name + val materialType = materialType() + + doAnswer { it.arguments[0] }.whenever(service).update(any()) + + val found = service.updateForNameAndMaterialType(mixType, name, materialType) + + verify(service).update(any()) + + assertEquals(mixType.id, found.id) + assertEquals(name, found.name) + assertEquals(name, found.material.name) + assertEquals(materialType, found.material.materialType) + assertTrue(found.material.isMixType) } } diff --git a/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/RecipeServiceTest.kt b/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/RecipeServiceTest.kt index d54f982..6886983 100644 --- a/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/RecipeServiceTest.kt +++ b/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/RecipeServiceTest.kt @@ -29,113 +29,107 @@ class RecipeServiceTest : override val entitySaveDto: RecipeSaveDto = spy(recipeSaveDto(name = entity.name, companyId = entity.company.id!!)) override val entityUpdateDto: RecipeUpdateDto = spy(recipeUpdateDto(id = entity.id!!, name = entity.name)) - @Nested - inner class ExistsByCompany { - @Test - fun `returns true when at least one recipe exists for the given company`() { - whenever(repository.existsByCompany(company)).doReturn(true) + // existsByCompany() - val found = service.existsByCompany(company) + @Test + fun `existsByCompany() returns true when at least one recipe exists for the given company`() { + whenever(repository.existsByCompany(company)).doReturn(true) - assertTrue(found) - } + val found = service.existsByCompany(company) - @Test - fun `returns false when no recipe exists for the given company`() { - whenever(repository.existsByCompany(company)).doReturn(false) - - val found = service.existsByCompany(company) - - assertFalse(found) - } + assertTrue(found) } - @Nested - inner class GetAllByCompany { - @Test - fun `returns the recipes with the given company`() { - val companies = listOf(entity, anotherEntity) - whenever(repository.findAllByCompany(company)).doReturn(companies) + @Test + fun `existsByCompany() returns false when no recipe exists for the given company`() { + whenever(repository.existsByCompany(company)).doReturn(false) - val found = service.getAllByCompany(company) + val found = service.existsByCompany(company) - assertEquals(companies, found) - } + assertFalse(found) } - @Nested - inner class SaveDto { - @Test - fun `calls and returns save() with the created entity`() { - whenever(companyService.getById(company.id!!)).doReturn(company) - saveDtoTest(entity, entitySaveDto, service) - } + // getAllByCompany() + + @Test + fun `getAllByCompany() returns the recipes with the given company`() { + val companies = listOf(entity, anotherEntity) + whenever(repository.findAllByCompany(company)).doReturn(companies) + + val found = service.getAllByCompany(company) + + assertEquals(companies, found) } - @Nested - inner class UpdatePublicDate { - @Test - fun `calls update with the updated note`() { - val publicDataDto = recipePublicDataDto(id = entity.id!!, note = "newNote", mixesLocation = null) - val expected = entity.apply { note = publicDataDto.note!! } - doReturn(entity).whenever(service).getById(entity.id!!) - doReturn(expected).whenever(service).update(expected) + // save() - service.updatePublicData(publicDataDto) - - verify(service).update(expected) - } - - @Test - fun `calls mixService_updateLocation() with every mix and locations`() { - val mix = mix(id = 0L) - val mixRecipe = entity.apply { mixes.add(mix) } - val location = "location" - val mixLocation = mapOf(mix.id!! to location) - val publicDataDto = recipePublicDataDto(id = mixRecipe.id!!, note = null, mixesLocation = mixLocation) - doReturn(mixRecipe).whenever(service).getById(mixRecipe.id!!) - - service.updatePublicData(publicDataDto) - - verify(mixService).updateLocation(mix, location) - } + @Test + override fun `save(dto) calls and returns save() with the created entity`() { + whenever(companyService.getById(company.id!!)).doReturn(company) + saveDtoTest(entity, entitySaveDto, service) } - @Nested - inner class AddMix { - @Test - fun `adds the given mix to the given recipe and updates it`() { - val mix = mix(id = 0L) - val recipe = recipe(id = 0L, mixes = mutableListOf()) + // updatePublicData() - doAnswer { it.arguments[0] }.whenever(service).update(any()) + @Test + fun `updatePublicData() calls update with the updated note`() { + val publicDataDto = recipePublicDataDto(id = entity.id!!, note = "newNote", mixesLocation = null) + val expected = entity.apply { note = publicDataDto.note!! } + doReturn(entity).whenever(service).getById(entity.id!!) + doReturn(expected).whenever(service).update(expected) - val found = service.addMix(recipe, mix) + service.updatePublicData(publicDataDto) - verify(service).update(any()) - - assertEquals(recipe.id, found.id) - assertTrue(found.mixes.contains(mix)) - } + verify(service).update(expected) } - @Nested - inner class RemoveMix { - @Test - fun `removes the given mix from its recipe and updates it`() { - val recipe = recipe(id = 0L, mixes = mutableListOf()) - val mix = mix(id = 0L, recipe = recipe) - recipe.mixes.add(mix) + @Test + fun `updatePublicData() calls mixService_updateLocation() with every mix and locations`() { + val mix = mix(id = 0L) + val mixRecipe = entity.apply { mixes.add(mix) } + val location = "location" + val mixLocation = mapOf(mix.id!! to location) + val publicDataDto = recipePublicDataDto(id = mixRecipe.id!!, note = null, mixesLocation = mixLocation) + doReturn(mixRecipe).whenever(service).getById(mixRecipe.id!!) - doAnswer { it.arguments[0] }.whenever(service).update(any()) + service.updatePublicData(publicDataDto) - val found = service.removeMix(mix) + verify(mixService).updateLocation(mix, location) + } - verify(service).update(any()) + // addMix() - assertEquals(recipe.id, found.id) - assertFalse(found.mixes.contains(mix)) - } + @Test + fun `addMix() adds the given mix to the given recipe and updates it`() { + val mix = mix(id = 0L) + val recipe = recipe(id = 0L, mixes = mutableListOf()) + + doAnswer { it.arguments[0] }.whenever(service).update(any()) + + val found = service.addMix(recipe, mix) + + verify(service).update(any()) + + assertEquals(recipe.id, found.id) + assertTrue(found.mixes.contains(mix)) + } + + // removeMix() + + @Test + fun `removeMix() removes the given mix from its recipe and updates it`() { + val recipe = recipe(id = 0L, mixes = mutableListOf()) + val mix = mix(id = 0L, recipe = recipe) + recipe.mixes.add(mix) + + doAnswer { it.arguments[0] }.whenever(service).update(any()) + + val found = service.removeMix(mix) + + verify(service).update(any()) + + assertEquals(recipe.id, found.id) + assertFalse(found.mixes.contains(mix)) } } @@ -158,121 +152,116 @@ class RecipeImageServiceTest { reset(recipeService, fileService, service, recipeDirectory) } - @Nested - inner class GetByIdForRecipe { - @Test - fun `returns data for the given recipe and image id red by the file service`() { - whenever(fileService.getPath(imagePath)).doReturn(imagePath) - whenever(fileService.readAsBytes(imagePath)).doReturn(imageData) + // getByIdForRecipe() - val found = service.getByIdForRecipe(imageId, recipeId) + @Test + fun `getByIdForRecipe() returns data for the given recipe and image id red by the file service`() { + whenever(fileService.getPath(imagePath)).doReturn(imagePath) + whenever(fileService.readAsBytes(imagePath)).doReturn(imageData) - assertEquals(imageData, found) - } + val found = service.getByIdForRecipe(imageId, recipeId) - @Test - fun `throws EntityNotFoundRestException when no image with the given recipe and image id exists`() { - doReturn(imagePath).whenever(service).getPath(imageId, recipeId) - whenever(fileService.readAsBytes(imagePath)).doThrow(NoSuchFileException(imagePath)) - - val exception = - assertThrows { service.getByIdForRecipe(imageId, recipeId) } - assertEquals("$recipeId/$imageId", exception.value) - } + assertEquals(imageData, found) } - @Nested - inner class GetAllIdsForRecipe { - @Test - fun `returns a list containing all image's identifier of the images of the given recipe`() { - val expectedFiles = imagesIds.map { File(it.toString()) }.toTypedArray() + @Test + fun `getByIdForRecipe() throws EntityNotFoundRestException when no image with the given recipe and image id exists`() { + doReturn(imagePath).whenever(service).getPath(imageId, recipeId) + whenever(fileService.readAsBytes(imagePath)).doThrow(NoSuchFileException(imagePath)) - whenever(recipeService.getById(recipeId)).doReturn(recipe) - whenever(recipeDirectory.exists()).doReturn(true) - whenever(recipeDirectory.isDirectory).doReturn(true) - whenever(recipeDirectory.listFiles()).doReturn(expectedFiles) - doReturn(recipeDirectory).whenever(service).getRecipeDirectory(recipeId) - - val found = service.getAllIdsForRecipe(recipeId) - - assertEquals(imagesIds, found) - } - - @Test - fun `returns an empty list when the given recipe's directory does not exists`() { - whenever(recipeService.getById(recipeId)).doReturn(recipe) - whenever(recipeDirectory.exists()).doReturn(false) - whenever(recipeDirectory.isDirectory).doReturn(true) - doReturn(recipeDirectory).whenever(service).getRecipeDirectory(recipeId) - - val found = service.getAllIdsForRecipe(recipeId) - - assertTrue(found.isEmpty()) - } - - @Test - fun `returns an empty list when the given recipe's directory is not a directory`() { - whenever(recipeService.getById(recipeId)).doReturn(recipe) - whenever(recipeDirectory.exists()).doReturn(true) - whenever(recipeDirectory.isDirectory).doReturn(false) - doReturn(recipeDirectory).whenever(service).getRecipeDirectory(recipeId) - - val found = service.getAllIdsForRecipe(recipeId) - - assertTrue(found.isEmpty()) - } + val exception = + assertThrows { service.getByIdForRecipe(imageId, recipeId) } + assertEquals("$recipeId/$imageId", exception.value) } - @Nested - inner class Save { - @Test - fun `writes the given image to the file service with the expected path`() { - val expectedNextAvailableId = imagesIds.maxOrNull()!! + 1 - val imagePath = "$RECIPE_IMAGES_DIRECTORY/$recipeId/$expectedNextAvailableId" - doReturn(imagesIds).whenever(service).getAllIdsForRecipe(recipeId) - doReturn(imagePath).whenever(service).getPath(expectedNextAvailableId, recipeId) + // getAllIdsForRecipe() - service.save(image, recipeId) + @Test + fun `getAllIdsForRecipe() returns a list containing all image's identifier of the images of the given recipe`() { + val expectedFiles = imagesIds.map { File(it.toString()) }.toTypedArray() - verify(fileService).write(image, imagePath) - } + whenever(recipeService.getById(recipeId)).doReturn(recipe) + whenever(recipeDirectory.exists()).doReturn(true) + whenever(recipeDirectory.isDirectory).doReturn(true) + whenever(recipeDirectory.listFiles()).doReturn(expectedFiles) + doReturn(recipeDirectory).whenever(service).getRecipeDirectory(recipeId) + + val found = service.getAllIdsForRecipe(recipeId) + + assertEquals(imagesIds, found) } - @Nested - inner class Delete { - @Test - fun `deletes the image with the given recipe and image id from the file service`() { - doReturn(imagePath).whenever(service).getPath(imageId, recipeId) + @Test + fun `getAllIdsForRecipe() returns an empty list when the given recipe's directory does not exists`() { + whenever(recipeService.getById(recipeId)).doReturn(recipe) + whenever(recipeDirectory.exists()).doReturn(false) + whenever(recipeDirectory.isDirectory).doReturn(true) + doReturn(recipeDirectory).whenever(service).getRecipeDirectory(recipeId) - service.delete(imageId, recipeId) + val found = service.getAllIdsForRecipe(recipeId) - verify(fileService).delete(imagePath) - } + assertTrue(found.isEmpty()) } - @Nested - inner class GetRecipeDirectory { - @Test - fun `returns a file with the expected path`() { - val recipeDirectoryPath = "$RECIPE_IMAGES_DIRECTORY/$recipeId" - whenever(fileService.getPath(recipeDirectoryPath)).doReturn(recipeDirectoryPath) + @Test + fun `getAllIdsForRecipe() returns an empty list when the given recipe's directory is not a directory`() { + whenever(recipeService.getById(recipeId)).doReturn(recipe) + whenever(recipeDirectory.exists()).doReturn(true) + whenever(recipeDirectory.isDirectory).doReturn(false) + doReturn(recipeDirectory).whenever(service).getRecipeDirectory(recipeId) - val found = service.getRecipeDirectory(recipeId) + val found = service.getAllIdsForRecipe(recipeId) - assertEquals(recipeDirectoryPath, found.path) - } + assertTrue(found.isEmpty()) } - @Nested - inner class GetPath { - @Test - fun `returns the expected path`() { - whenever(fileService.getPath(any())).doAnswer { it.arguments[0] as String } + // save() - val found = service.getPath(imageId, recipeId) + @Test + fun `save() writes the given image to the file service with the expected path`() { + val expectedNextAvailableId = imagesIds.maxOrNull()!! + 1 + val imagePath = "$RECIPE_IMAGES_DIRECTORY/$recipeId/$expectedNextAvailableId" - assertEquals(imagePath, found) - } + doReturn(imagesIds).whenever(service).getAllIdsForRecipe(recipeId) + doReturn(imagePath).whenever(service).getPath(expectedNextAvailableId, recipeId) + + service.save(image, recipeId) + + verify(fileService).write(image, imagePath) + } + + // delete() + + @Test + fun `delete() deletes the image with the given recipe and image id from the file service`() { + doReturn(imagePath).whenever(service).getPath(imageId, recipeId) + + service.delete(imageId, recipeId) + + verify(fileService).delete(imagePath) + } + + // getRecipeDirectory() + + @Test + fun `getRecipeDirectory() returns a file with the expected path`() { + val recipeDirectoryPath = "$RECIPE_IMAGES_DIRECTORY/$recipeId" + whenever(fileService.getPath(recipeDirectoryPath)).doReturn(recipeDirectoryPath) + + val found = service.getRecipeDirectory(recipeId) + + assertEquals(recipeDirectoryPath, found.path) + } + + // getPath() + + @Test + fun `getPath() returns the expected path`() { + whenever(fileService.getPath(any())).doAnswer { it.arguments[0] as String } + + val found = service.getPath(imageId, recipeId) + + assertEquals(imagePath, found) } } diff --git a/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/RecipeStepServiceTest.kt b/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/RecipeStepServiceTest.kt index beb6bed..4109030 100644 --- a/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/RecipeStepServiceTest.kt +++ b/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/RecipeStepServiceTest.kt @@ -5,6 +5,7 @@ import com.nhaarman.mockitokotlin2.spy import dev.fyloz.trial.colorrecipesexplorer.model.* import dev.fyloz.trial.colorrecipesexplorer.repository.RecipeStepRepository import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test import kotlin.test.assertEquals class RecipeStepServiceTest : @@ -15,29 +16,29 @@ class RecipeStepServiceTest : override val entity: RecipeStep = recipeStep(id = 0L, recipe = recipe(id = 0L), message = "message") override val anotherEntity: RecipeStep = recipeStep(id = 1L, recipe = recipe(id = 1L), message = "another message") - @Nested - inner class CreateForRecipe { - fun `returns a correct RecipeStep`() { - val step = recipeStep(null, entity.recipe, entity.message) + // createForRecipe() - val found = service.createForRecipe(entity.recipe!!, entity.message) + @Test + fun `createForRecipe() returns a correct RecipeStep`() { + val step = recipeStep(null, entity.recipe, entity.message) - assertEquals(step, found) - } + val found = service.createForRecipe(entity.recipe!!, entity.message) + + assertEquals(step, found) } - @Nested - inner class CreateAllForRecipe { - fun `returns all correct RecipeSteps`() { - val steps = listOf( - recipeStep(null, entity.recipe, entity.message), - recipeStep(null, entity.recipe, anotherEntity.message) - ) - val messages = steps.map { it.message } + // createAllForRecipe() - val found = service.createAllForRecipe(entity.recipe!!, messages) + @Test + fun `createAllForRecipe() returns all correct RecipeSteps`() { + val steps = listOf( + recipeStep(null, entity.recipe, entity.message), + recipeStep(null, entity.recipe, anotherEntity.message) + ) + val messages = steps.map { it.message } - assertEquals(steps, found) - } + val found = service.createAllForRecipe(entity.recipe!!, messages) + + assertEquals(steps, found) } } From 08c6a9db4999bd79e8e133bd15351c92f40b0c61 Mon Sep 17 00:00:00 2001 From: FyloZ Date: Mon, 8 Mar 2021 13:56:59 -0500 Subject: [PATCH 2/4] Correction du test update(dto) --- build.gradle.kts | 2 +- .../service/AbstractServiceTest.kt | 80 +++++++++---------- .../service/AccountsServiceTest.kt | 9 ++- .../service/CompanyServiceTest.kt | 8 ++ .../service/MaterialServiceTest.kt | 30 +++---- .../service/MaterialTypeServiceTest.kt | 3 + .../service/MixServiceTest.kt | 61 ++++++++++++++ .../service/RecipeServiceTest.kt | 8 +- 8 files changed, 139 insertions(+), 62 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 46876d0..9b2fb99 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -81,7 +81,7 @@ tasks.test { useJUnitPlatform() testLogging { - events("passed", "skipped", "failed") + events("skipped", "failed") } } diff --git a/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/AbstractServiceTest.kt b/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/AbstractServiceTest.kt index 097aaec..ff0baf2 100644 --- a/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/AbstractServiceTest.kt +++ b/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/AbstractServiceTest.kt @@ -1,9 +1,6 @@ package dev.fyloz.trial.colorrecipesexplorer.service -import com.nhaarman.mockitokotlin2.doReturn -import com.nhaarman.mockitokotlin2.reset -import com.nhaarman.mockitokotlin2.verify -import com.nhaarman.mockitokotlin2.whenever +import com.nhaarman.mockitokotlin2.* import dev.fyloz.trial.colorrecipesexplorer.exception.model.EntityAlreadyExistsRestException import dev.fyloz.trial.colorrecipesexplorer.exception.model.EntityNotFoundRestException import dev.fyloz.trial.colorrecipesexplorer.model.EntityDto @@ -11,7 +8,6 @@ import dev.fyloz.trial.colorrecipesexplorer.model.Model import dev.fyloz.trial.colorrecipesexplorer.model.NamedModel import dev.fyloz.trial.colorrecipesexplorer.repository.NamedJpaRepository import org.junit.jupiter.api.AfterEach -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows import org.springframework.data.jpa.repository.JpaRepository @@ -19,6 +15,7 @@ import java.util.* import kotlin.test.assertEquals import kotlin.test.assertFalse import kotlin.test.assertTrue +import dev.fyloz.trial.colorrecipesexplorer.service.AbstractServiceTest as AbstractServiceTest1 abstract class AbstractServiceTest, R : JpaRepository> { protected abstract val repository: R @@ -93,7 +90,7 @@ abstract class AbstractServiceTest, R : JpaRepository } abstract class AbstractModelServiceTest, R : JpaRepository> : - AbstractServiceTest() { + AbstractServiceTest1() { // existsById() @@ -279,10 +276,15 @@ abstract class AbstractNamedModelServiceTest, U : EntityDto, S : ExternalModelService, R : JpaRepository> : - AbstractModelServiceTest() { + AbstractModelServiceTest(), ExternalModelServiceTest { protected abstract val entitySaveDto: N protected abstract val entityUpdateDto: U @@ -292,21 +294,12 @@ abstract class AbstractExternalModelServiceTest, U : super.afterEach() } - // save() - - @Test - open fun `save(dto) calls and returns save() with the created entity`() = - saveDtoTest(entity, entitySaveDto, service) - - // update() - - @Test - open fun `update(dto) calls and returns update() with the created entity`() = - updateDtoTest(entity, entityUpdateDto, service) + override fun `save(dto) calls and returns save() with the created entity`() = + withBaseSaveDtoTest(entity, entitySaveDto, service) } abstract class AbstractExternalNamedModelServiceTest, U : EntityDto, S : ExternalNamedModelService, R : NamedJpaRepository> : - AbstractNamedModelServiceTest() { + AbstractNamedModelServiceTest(), ExternalModelServiceTest { protected abstract val entitySaveDto: N protected abstract val entityUpdateDto: U @@ -316,20 +309,16 @@ abstract class AbstractExternalNamedModelServiceTest> saveDtoTest(entity: E, entitySaveDto: N, service: ExternalService) { +fun > withBaseSaveDtoTest( + entity: E, + entitySaveDto: N, + service: ExternalService, + op: () -> Unit = {} +) { doReturn(entity).whenever(service).save(entity) doReturn(entity).whenever(entitySaveDto).toEntity() @@ -337,21 +326,26 @@ fun > saveDtoTest(entity: E, entitySaveDto: N, service: Exte verify(service).save(entity) assertEquals(entity, found) + + op() } -fun > updateDtoTest( +fun > withBaseUpdateDtoTest( entity: E, entityUpdateDto: U, - service: ExternalModelService + service: ExternalModelService, + updateMockMatcher: E, + op: () -> Unit = {} ) { -// doReturn(entity).whenever(service).update(entity) -// doReturn(entity).whenever(entityUpdateDto).toEntity() -// doReturn(entity).whenever(service).getById(entity.id!!) -// doReturn(true).whenever(service).existsById(entity.id!!) -// -// val found = service.update(entityUpdateDto) -// -// verify(service).update(entity) -// assertEquals(entity, found) - assertTrue(true, "Disabled because the wrong methods are mocked for some reason") + doAnswer { it.arguments[0] }.whenever(service).update(updateMockMatcher) + doReturn(entity).whenever(entityUpdateDto).toEntity() + doReturn(entity).whenever(service).getById(entity.id!!) + doReturn(true).whenever(service).existsById(entity.id!!) + + val found = service.update(entityUpdateDto) + + verify(service).update(updateMockMatcher) + assertEquals(entity, found) + + op() } diff --git a/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/AccountsServiceTest.kt b/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/AccountsServiceTest.kt index da872a2..b862d96 100644 --- a/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/AccountsServiceTest.kt +++ b/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/AccountsServiceTest.kt @@ -1,7 +1,6 @@ package dev.fyloz.trial.colorrecipesexplorer.service import com.nhaarman.mockitokotlin2.* -import dev.fyloz.trial.colorrecipesexplorer.config.SecurityConfigurationProperties import dev.fyloz.trial.colorrecipesexplorer.config.defaultGroupCookieName import dev.fyloz.trial.colorrecipesexplorer.exception.model.EntityAlreadyExistsRestException import dev.fyloz.trial.colorrecipesexplorer.exception.model.EntityNotFoundRestException @@ -169,6 +168,9 @@ class EmployeeServiceTest : // update() + override fun `update(dto) calls and returns update() with the created entity`() = + withBaseUpdateDtoTest(entity, entityUpdateDto, service, any()) + @Test fun `update() throws EntityAlreadyExistsRestException when a different employee with the given first name and last name exists`() { whenever(repository.findByFirstNameAndLastName(entity.firstName, entity.lastName)).doReturn( @@ -392,6 +394,11 @@ class EmployeeGroupServiceTest : verify(service, times(0)).update(group) verify(employeeService, times(0)).update(employee) } + + // update() + + override fun `update(dto) calls and returns update() with the created entity`() = + withBaseUpdateDtoTest(entity, entityUpdateDto, service, any()) } class EmployeeUserDetailsServiceTest { diff --git a/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/CompanyServiceTest.kt b/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/CompanyServiceTest.kt index 450336a..458f688 100644 --- a/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/CompanyServiceTest.kt +++ b/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/CompanyServiceTest.kt @@ -6,6 +6,7 @@ import dev.fyloz.trial.colorrecipesexplorer.repository.CompanyRepository import dev.fyloz.trial.colorrecipesexplorer.service.model.RecipeJavaService import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test import kotlin.test.assertFalse import kotlin.test.assertTrue @@ -29,6 +30,7 @@ class CompanyServiceTest : // isLinkedToRecipes + @Test fun `isLinkedToRecipes() returns true when a given company is linked to one or more recipes`() { whenever(recipeService.existsByCompany(entity)).doReturn(true) @@ -37,6 +39,7 @@ class CompanyServiceTest : assertTrue(found) } + @Test fun `isLinkedToRecipes() returns false when a given company is not linked to any recipe`() { whenever(recipeService.existsByCompany(entity)).doReturn(false) @@ -44,4 +47,9 @@ class CompanyServiceTest : assertFalse(found) } + + // update() + + override fun `update(dto) calls and returns update() with the created entity`() = + withBaseUpdateDtoTest(entity, entityUpdateDto, service, any()) } diff --git a/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MaterialServiceTest.kt b/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MaterialServiceTest.kt index d8b0303..24ed8a4 100644 --- a/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MaterialServiceTest.kt +++ b/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MaterialServiceTest.kt @@ -175,21 +175,21 @@ class MaterialServiceTest : assertFalse(found contains anotherMixTypeMaterial) } -// @Nested -// inner class UpdateDto { -// @Test -// fun `calls simdutService_update() with the updated entity`() { -// val mockSimdutFile = MockMultipartFile("simdut", byteArrayOf(0)) -// val materialUpdateDto = spy(materialUpdateDto(id = 0L, simdutFile = mockSimdutFile)) -// -// doReturn(entity).whenever(service).update(entity) -// doReturn(entity).whenever(materialUpdateDto).toEntity() -// -// service.update(materialUpdateDto) -// -// verify(simdutService).update(mockSimdutFile, entity) -// } -// } + // update() + + @Test + override fun `update(dto) calls and returns update() with the created entity`() { + val mockSimdutFile = MockMultipartFile("simdut", byteArrayOf(1, 2, 3, 4, 5)) + val materialUpdateDto = spy(materialUpdateDto(id = 0L, simdutFile = mockSimdutFile)) + + doReturn(entity).whenever(service).getById(materialUpdateDto.id) + doReturn(entity).whenever(service).update(any()) + doReturn(entity).whenever(materialUpdateDto).toEntity() + + service.update(materialUpdateDto) + + verify(simdutService).update(eq(mockSimdutFile), any()) + } /** Helper function to replace collections.in because the id is not considered in the equals function of Material while Thymeleaf is supported. */ private infix fun Collection.contains(material: Material): Boolean = diff --git a/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MaterialTypeServiceTest.kt b/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MaterialTypeServiceTest.kt index 04e85a3..802cdd3 100644 --- a/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MaterialTypeServiceTest.kt +++ b/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MaterialTypeServiceTest.kt @@ -109,6 +109,9 @@ class MaterialTypeServiceTest : // update() + override fun `update(dto) calls and returns update() with the created entity`() = + withBaseUpdateDtoTest(entity, entityUpdateDto, service, any()) + override fun `update() saves in the repository and returns the updated value`() { whenever(repository.save(entity)).doReturn(entity) whenever(repository.findByName(entity.name)).doReturn(null) diff --git a/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MixServiceTest.kt b/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MixServiceTest.kt index 71dc035..30e38e0 100644 --- a/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MixServiceTest.kt +++ b/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MixServiceTest.kt @@ -73,6 +73,67 @@ class MixServiceTest : AbstractExternalModelServiceTest()) + + whenever(materialTypeService.getById(materialType.id!!)).doReturn(materialType) + whenever(mixTypeService.createForNameAndMaterialType(mixUpdateDto.name!!, materialType)).doReturn(newMixType) + + val found = service.update(mixUpdateDto) + + verify(mixTypeService).createForNameAndMaterialType(mixUpdateDto.name!!, materialType) + + assertEquals(newMixType, found.mixType) + } + + @Test + fun `update(dto) calls MixTypeService updateForNameAndMaterialType() when mix type is not shared`() { + val mixType = mixType(name = "mix type") + val newMixType = mixType(name = "another mix type") + val mix = mix(id = 0L, mixType = mixType) + val materialType = materialType(id = 0L) + val mixUpdateDto = spy(mixUpdateDto(id = 0L, name = "mix", materialTypeId = 0L, mixMaterials = null)) + + doReturn(true).whenever(service).existsById(mix.id!!) + doReturn(mix).whenever(service).getById(mix.id!!) + doReturn(false).whenever(service).mixTypeIsShared(mix.mixType) + doAnswer { it.arguments[0] }.whenever(service).update(any()) + + whenever(materialTypeService.getById(materialType.id!!)).doReturn(materialType) + whenever(mixTypeService.updateForNameAndMaterialType(mixType, mixUpdateDto.name!!, materialType)).doReturn(newMixType) + + val found = service.update(mixUpdateDto) + + verify(mixTypeService).updateForNameAndMaterialType(mixType, mixUpdateDto.name!!, materialType) + + assertEquals(newMixType, found.mixType) + } + // updateLocation() @Test diff --git a/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/RecipeServiceTest.kt b/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/RecipeServiceTest.kt index 6886983..b03d4af 100644 --- a/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/RecipeServiceTest.kt +++ b/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/RecipeServiceTest.kt @@ -6,7 +6,6 @@ import dev.fyloz.trial.colorrecipesexplorer.model.* import dev.fyloz.trial.colorrecipesexplorer.repository.RecipeRepository import dev.fyloz.trial.colorrecipesexplorer.service.files.FilesService import org.junit.jupiter.api.AfterEach -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows import org.springframework.mock.web.MockMultipartFile @@ -66,9 +65,14 @@ class RecipeServiceTest : @Test override fun `save(dto) calls and returns save() with the created entity`() { whenever(companyService.getById(company.id!!)).doReturn(company) - saveDtoTest(entity, entitySaveDto, service) + withBaseSaveDtoTest(entity, entitySaveDto, service) } + // update() + + override fun `update(dto) calls and returns update() with the created entity`() = + withBaseUpdateDtoTest(entity, entityUpdateDto, service, any()) + // updatePublicData() @Test From 50442d7ebc84a4bd38f49b3f55cba41158b13565 Mon Sep 17 00:00:00 2001 From: FyloZ Date: Tue, 9 Mar 2021 11:45:00 -0500 Subject: [PATCH 3/4] =?UTF-8?q?La=20mise=20=C3=A0=20jour=20d'un=20m=C3=A9l?= =?UTF-8?q?ange=20cr=C3=A9e,=20met=20=C3=A0=20jour=20et=20supprime=20les?= =?UTF-8?q?=20ingr=C3=A9dients=20au=20lieu=20de=20tout=20recr=C3=A9er.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../colorrecipesexplorer/model/MixMaterial.kt | 2 +- .../service/MixMaterialService.kt | 20 ++- .../service/MixService.kt | 28 +++- .../service/MixMaterialServiceTest.kt | 68 ++++++++-- .../service/MixServiceTest.kt | 120 +++++++++++++----- 5 files changed, 189 insertions(+), 49 deletions(-) diff --git a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/model/MixMaterial.kt b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/model/MixMaterial.kt index cbad684..95a7660 100644 --- a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/model/MixMaterial.kt +++ b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/model/MixMaterial.kt @@ -20,7 +20,7 @@ data class MixMaterial( @JoinColumn(name = "material_id") val material: Material, - val quantity: Float + var quantity: Float ) : Model { constructor(mix: Mix, material: Material, quantity: Float) : this(null, mix, material, quantity) diff --git a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MixMaterialService.kt b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MixMaterialService.kt index 925000d..d280eab 100644 --- a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MixMaterialService.kt +++ b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MixMaterialService.kt @@ -15,8 +15,11 @@ interface MixMaterialService : ModelService /** Creates [MixMaterial]s from the given [map]. The [map] must have the format . */ fun createFromMap(mix: Mix, map: Map): Collection - /** Creates a [MixMaterial] from the given [pair]. The [pair] must have the format . */ - fun createFromPair(mix: Mix, pair: Pair): MixMaterial + /** Creates a [MixMaterial] with the material with the given [materialId] and the given [quantity]. */ + fun create(mix: Mix, materialId: Long, quantity: Float): MixMaterial + + /** Updates the [quantity] of the given [mixMaterial]. */ + fun updateQuantity(mixMaterial: MixMaterial, quantity: Float): MixMaterial } @Service @@ -26,10 +29,13 @@ class MixMaterialServiceImpl( ) : AbstractModelService(mixMaterialRepository), MixMaterialService { override fun existsByMaterial(material: Material): Boolean = repository.existsByMaterial(material) override fun createFromMap(mix: Mix, map: Map): Collection = - map.map { createFromPair(mix, it.toPair()) } + map.map { create(mix, it.key, it.value) } - override fun createFromPair(mix: Mix, pair: Pair): MixMaterial { - val material = materialService.getById(pair.first) - return mixMaterial(mix = mix, material = material, quantity = pair.second) - } + override fun create(mix: Mix, materialId: Long, quantity: Float): MixMaterial = + mixMaterial(mix = mix, material = materialService.getById(materialId), quantity = quantity) + + override fun updateQuantity(mixMaterial: MixMaterial, quantity: Float) = + update(mixMaterial.apply { + this.quantity = quantity + }) } diff --git a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MixService.kt b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MixService.kt index 98fbb08..386e65b 100644 --- a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MixService.kt +++ b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MixService.kt @@ -53,7 +53,33 @@ class MixServiceImpl( return mix } + @Transactional override fun update(entity: MixUpdateDto): Mix { + fun updateMixMaterials(mix: Mix, mixMaterialsMap: Map) { + val existingMixMaterialsMaterialIds = mix.mixMaterials.map { it.material.id } + val toDelete = mix.mixMaterials + + mix.mixMaterials = mutableListOf( + // update existing mix materials + *mixMaterialsMap + .filter { it.key in existingMixMaterialsMaterialIds } + .map { (materialId, quantity) -> + val existingMixMaterial = mix.mixMaterials.first { it.material.id == materialId } + toDelete.remove(existingMixMaterial) + mixMaterialService.updateQuantity(existingMixMaterial, quantity) + } + .toTypedArray(), + // create new mix materials + *mixMaterialsMap + .filter { it.key !in existingMixMaterialsMaterialIds } + .map { (materialId, quantity) -> mixMaterialService.create(mix, materialId, quantity) } + .toTypedArray() + ) + + // delete unused mix materials + toDelete.forEach { mixMaterialService.delete(it) } + } + val mix = getById(entity.id) if (entity.name != null || entity.materialTypeId != null) { mix.mixType = if (mixTypeIsShared(mix.mixType)) { @@ -70,7 +96,7 @@ class MixServiceImpl( } } if (entity.mixMaterials != null) { - mix.mixMaterials = mixMaterialService.createFromMap(mix, entity.mixMaterials).toMutableList() + updateMixMaterials(mix, entity.mixMaterials) } return update(mix) } diff --git a/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MixMaterialServiceTest.kt b/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MixMaterialServiceTest.kt index 698a0b5..fb42bb2 100644 --- a/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MixMaterialServiceTest.kt +++ b/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MixMaterialServiceTest.kt @@ -1,16 +1,12 @@ package dev.fyloz.trial.colorrecipesexplorer.service -import com.nhaarman.mockitokotlin2.doReturn -import com.nhaarman.mockitokotlin2.mock -import com.nhaarman.mockitokotlin2.spy -import com.nhaarman.mockitokotlin2.whenever -import dev.fyloz.trial.colorrecipesexplorer.model.Material -import dev.fyloz.trial.colorrecipesexplorer.model.MixMaterial -import dev.fyloz.trial.colorrecipesexplorer.model.material -import dev.fyloz.trial.colorrecipesexplorer.model.mixMaterial +import com.nhaarman.mockitokotlin2.* +import dev.fyloz.trial.colorrecipesexplorer.model.* import dev.fyloz.trial.colorrecipesexplorer.repository.MixMaterialRepository -import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals import kotlin.test.assertFalse +import kotlin.test.assertNotEquals import kotlin.test.assertTrue class MixMaterialServiceTest : AbstractModelServiceTest() { @@ -19,11 +15,12 @@ class MixMaterialServiceTest : AbstractModelServiceTest mixMaterial.material.id == it.arguments[1] } } + .whenever(service).create(eq(mix), any(), any()) + + val found = service.createFromMap(mix, map) + + assertEquals(mixMaterials, found) + } + + // create() + + @Test + fun `create() creates a mix material with the given mix, material and quantity`() { + val mix = mix() + val material = material(id = 0L) + val quantity = 1000f + val mixMaterial = mixMaterial(mix = mix, material = material, quantity = quantity) + + whenever(materialService.getById(material.id!!)).doReturn(material) + + val found = service.create(mix, material.id!!, quantity) + + assertEquals(mixMaterial, found) + } + + // updateQuantity() + + @Test + fun `updateQuantity() updates the given mix material with the given quantity`() { + val quantity = 5000f + assertNotEquals(quantity, entity.quantity, message = "Quantities must not be equals for this test to works") + + doAnswer { it.arguments[0] }.whenever(service).update(any()) + + val found = service.updateQuantity(entity, quantity) + + assertEquals(found.quantity, quantity) + } } diff --git a/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MixServiceTest.kt b/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MixServiceTest.kt index 30e38e0..728f344 100644 --- a/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MixServiceTest.kt +++ b/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MixServiceTest.kt @@ -3,9 +3,9 @@ package dev.fyloz.trial.colorrecipesexplorer.service import com.nhaarman.mockitokotlin2.* import dev.fyloz.trial.colorrecipesexplorer.model.* import dev.fyloz.trial.colorrecipesexplorer.repository.MixRepository -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test import kotlin.test.assertEquals +import kotlin.test.assertTrue class MixServiceTest : AbstractExternalModelServiceTest() { override val repository: MixRepository = mock() @@ -75,6 +75,31 @@ class MixServiceTest : AbstractExternalModelServiceTest Unit + ) { + with(scope) { + doReturn(true).whenever(service).existsById(mix.id!!) + doReturn(mix).whenever(service).getById(mix.id!!) + doReturn(sharedMixType).whenever(service).mixTypeIsShared(mix.mixType) + doAnswer { it.arguments[0] }.whenever(service).update(any()) + + if (mixUpdateDto.materialTypeId != null) { + whenever(materialTypeService.getById(materialType.id!!)).doReturn(materialType) + } + + op() + } + } + + private fun mixUpdateDtoMixTypeTest(sharedMixType: Boolean = false, op: MixUpdateDtoTestScope.() -> Unit) { + with(MixUpdateDtoTestScope(mixUpdateDto = mixUpdateDto(id = 0L, name = "name", materialTypeId = 0L))) { + mixUpdateDtoTest(this, sharedMixType, op) + } + } + @Test override fun `update(dto) calls and returns update() with the created entity`() { val mixUpdateDto = spy(mixUpdateDto(id = 0L, name = null, materialTypeId = null)) @@ -91,47 +116,67 @@ class MixServiceTest : AbstractExternalModelServiceTest()) + val found = service.update(mixUpdateDto) - whenever(materialTypeService.getById(materialType.id!!)).doReturn(materialType) - whenever(mixTypeService.createForNameAndMaterialType(mixUpdateDto.name!!, materialType)).doReturn(newMixType) + verify(mixTypeService).createForNameAndMaterialType(mixUpdateDto.name!!, materialType) - val found = service.update(mixUpdateDto) - - verify(mixTypeService).createForNameAndMaterialType(mixUpdateDto.name!!, materialType) - - assertEquals(newMixType, found.mixType) + assertEquals(newMixType, found.mixType) + } } @Test fun `update(dto) calls MixTypeService updateForNameAndMaterialType() when mix type is not shared`() { - val mixType = mixType(name = "mix type") - val newMixType = mixType(name = "another mix type") - val mix = mix(id = 0L, mixType = mixType) - val materialType = materialType(id = 0L) - val mixUpdateDto = spy(mixUpdateDto(id = 0L, name = "mix", materialTypeId = 0L, mixMaterials = null)) + mixUpdateDtoMixTypeTest { + whenever(mixTypeService.updateForNameAndMaterialType(mixType, mixUpdateDto.name!!, materialType)) + .doReturn(newMixType) - doReturn(true).whenever(service).existsById(mix.id!!) - doReturn(mix).whenever(service).getById(mix.id!!) - doReturn(false).whenever(service).mixTypeIsShared(mix.mixType) - doAnswer { it.arguments[0] }.whenever(service).update(any()) + val found = service.update(mixUpdateDto) - whenever(materialTypeService.getById(materialType.id!!)).doReturn(materialType) - whenever(mixTypeService.updateForNameAndMaterialType(mixType, mixUpdateDto.name!!, materialType)).doReturn(newMixType) + verify(mixTypeService).updateForNameAndMaterialType(mixType, mixUpdateDto.name!!, materialType) - val found = service.update(mixUpdateDto) + assertEquals(newMixType, found.mixType) + } + } - verify(mixTypeService).updateForNameAndMaterialType(mixType, mixUpdateDto.name!!, materialType) + @Test + fun `update(dto) update, create and delete mix materials according to the given mix materials map`() { + mixUpdateDtoTest { + // Pairs exists, impairs don't + val materials = listOf( + material(id = 1L), + material(id = 2L), + material(id = 3L), + material(id = 4L), + material(id = 5L), + material(id = 6L), + ) + val toDelete = mixMaterial(material = material(id = 7L), quantity = 7000f) + val mixMaterialsMap = mapOf(*materials.map { it.id!! to it.id!! * 1000f }.toTypedArray()) + val allMixMaterials: Collection = materials + .map { mixMaterial(mix = mix, material = it, quantity = mixMaterialsMap[it.id]!!) } + val existingMixMaterials = allMixMaterials.filter { it.material.id!! % 2 == 0L }.toMutableList() + existingMixMaterials += toDelete - assertEquals(newMixType, found.mixType) + mix.mixMaterials = existingMixMaterials + (mixUpdateDto.mixMaterials as MutableMap).putAll(mixMaterialsMap) + + doAnswer { allMixMaterials.first { mixMaterial -> mixMaterial.material.id == (it.arguments[0] as MixMaterial).material.id } } + .whenever(mixMaterialService).updateQuantity(any(), any()) + doAnswer { allMixMaterials.first { mixMaterial -> mixMaterial.material.id == it.arguments[1] } } + .whenever(mixMaterialService).create(eq(mix), any(), any()) + + val found: Mix = service.update(mixUpdateDto) + + assertTrue { found.mixMaterials.containsAll(allMixMaterials) } + + verify(mixMaterialService, times(3)).updateQuantity(argThat { material.id!! % 2 == 0L }, any()) + verify(mixMaterialService, times(3)).create(eq(mix), any(), any()) + verify(mixMaterialService).delete(toDelete) + } } // updateLocation() @@ -147,3 +192,18 @@ class MixServiceTest : AbstractExternalModelServiceTest Date: Tue, 9 Mar 2021 14:08:57 -0500 Subject: [PATCH 4/4] Cleanup --- build.gradle.kts | 6 +++- .../exception/RestException.kt | 5 +-- .../model/EntityAlreadyExistsException.kt | 27 ++++++++++++--- .../model/EntityNotFoundException.kt | 13 +++++--- .../service/model/MixTypeJavaService.java | 2 +- .../ColorRecipesExplorerApplication.kt | 7 +--- .../config/WebSecurityConfig.kt | 10 +++--- .../model/AccountModel.kt | 33 +++++-------------- .../colorrecipesexplorer/model/Material.kt | 2 +- .../trial/colorrecipesexplorer/model/Model.kt | 6 ++-- .../colorrecipesexplorer/model/Recipe.kt | 13 ++++++++ .../colorrecipesexplorer/model/RecipeStep.kt | 2 -- .../model/validation/NullOrNotBlank.kt | 7 ++-- .../model/validation/NullOrSize.kt | 4 +-- .../rest/InventoryController.kt | 4 +-- .../rest/RestApiController.kt | 2 +- .../service/AccountService.kt | 8 ++--- .../service/InventoryService.kt | 8 ----- .../service/MaterialTypeService.kt | 5 ++- .../service/RecipeService.kt | 2 +- .../colorrecipesexplorer/service/Service.kt | 2 +- .../repository/RecipeStepRepositoryTest.kt | 1 + 22 files changed, 83 insertions(+), 86 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 9b2fb99..9922be4 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -90,7 +90,11 @@ tasks.withType { } tasks.withType { - kotlinOptions.jvmTarget = "11" + kotlinOptions { + jvmTarget = "11" + useIR = true + freeCompilerArgs = freeCompilerArgs + "-Xopt-in=kotlin.contracts.ExperimentalContracts" + } } tasks.dokkaHtml { diff --git a/src/main/java/dev/fyloz/trial/colorrecipesexplorer/exception/RestException.kt b/src/main/java/dev/fyloz/trial/colorrecipesexplorer/exception/RestException.kt index 1679f96..137afb9 100644 --- a/src/main/java/dev/fyloz/trial/colorrecipesexplorer/exception/RestException.kt +++ b/src/main/java/dev/fyloz/trial/colorrecipesexplorer/exception/RestException.kt @@ -13,12 +13,9 @@ import org.springframework.web.bind.annotation.ExceptionHandler import org.springframework.web.context.request.WebRequest import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler -abstract class RestException(val httpStatus: HttpStatus) : RuntimeException() { - abstract val exceptionMessage: String +abstract class RestException(val exceptionMessage: String, val httpStatus: HttpStatus) : RuntimeException(exceptionMessage) { abstract fun buildBody(): RestExceptionBody - override val message: String by lazy { exceptionMessage } - open inner class RestExceptionBody(val status: Int = httpStatus.value(), @JsonProperty("message") val message: String = exceptionMessage) } diff --git a/src/main/java/dev/fyloz/trial/colorrecipesexplorer/exception/model/EntityAlreadyExistsException.kt b/src/main/java/dev/fyloz/trial/colorrecipesexplorer/exception/model/EntityAlreadyExistsException.kt index 042a9e0..26232c5 100644 --- a/src/main/java/dev/fyloz/trial/colorrecipesexplorer/exception/model/EntityAlreadyExistsException.kt +++ b/src/main/java/dev/fyloz/trial/colorrecipesexplorer/exception/model/EntityAlreadyExistsException.kt @@ -5,15 +5,32 @@ import dev.fyloz.trial.colorrecipesexplorer.model.Model import org.springframework.http.HttpStatus import org.springframework.web.bind.annotation.ResponseStatus -class EntityAlreadyExistsException(modelType: Class, val identifierType: IdentifierType, val identifierName: String?, val requestedId: Any) : ModelException(modelType) { - constructor(modelType: Class, identifierType: IdentifierType, requestedId: Any) : this(modelType, identifierType, identifierType.name, requestedId) - constructor(exception: EntityAlreadyExistsException) : this(exception.type, exception.identifierType, exception.identifierName, exception.requestedId) +class EntityAlreadyExistsException( + modelType: Class, + val identifierType: IdentifierType, + val identifierName: String?, + val requestedId: Any +) : ModelException(modelType) { + constructor(modelType: Class, identifierType: IdentifierType, requestedId: Any) : this( + modelType, + identifierType, + identifierType.name, + requestedId + ) + + constructor(exception: EntityAlreadyExistsException) : this( + exception.type, + exception.identifierType, + exception.identifierName, + exception.requestedId + ) } @ResponseStatus(HttpStatus.CONFLICT) -class EntityAlreadyExistsRestException(val value: Any) : RestException(HttpStatus.CONFLICT) { - override val exceptionMessage: String = "An entity with the given identifier already exists" +class EntityAlreadyExistsRestException(val value: Any) : + RestException("An entity with the given identifier already exists", HttpStatus.CONFLICT) { + @Suppress("unused") override fun buildBody(): RestExceptionBody = object : RestExceptionBody() { val id = value } diff --git a/src/main/java/dev/fyloz/trial/colorrecipesexplorer/exception/model/EntityNotFoundException.kt b/src/main/java/dev/fyloz/trial/colorrecipesexplorer/exception/model/EntityNotFoundException.kt index fe499fd..e40eb45 100644 --- a/src/main/java/dev/fyloz/trial/colorrecipesexplorer/exception/model/EntityNotFoundException.kt +++ b/src/main/java/dev/fyloz/trial/colorrecipesexplorer/exception/model/EntityNotFoundException.kt @@ -5,14 +5,17 @@ import dev.fyloz.trial.colorrecipesexplorer.model.Model import org.springframework.http.HttpStatus import org.springframework.web.bind.annotation.ResponseStatus -class EntityNotFoundException(modelType: Class, val identifierType: IdentifierType, val identifierName: String, val requestedId: Any) : ModelException(modelType) { - constructor(modelType: Class, identifierType: IdentifierType, requestedId: Any) : this(modelType, identifierType, identifierType.name, requestedId) -} +class EntityNotFoundException( + modelType: Class, + val identifierType: IdentifierType, + val requestedId: Any +) : ModelException(modelType) @ResponseStatus(HttpStatus.NOT_FOUND) -class EntityNotFoundRestException(val value: Any) : RestException(HttpStatus.NOT_FOUND) { - override val exceptionMessage: String = "An entity could not be found with the given identifier" +class EntityNotFoundRestException(val value: Any) : + RestException("An entity could not be found with the given identifier", HttpStatus.NOT_FOUND) { + @Suppress("unused") override fun buildBody(): RestExceptionBody = object : RestExceptionBody() { val id = value } diff --git a/src/main/java/dev/fyloz/trial/colorrecipesexplorer/service/model/MixTypeJavaService.java b/src/main/java/dev/fyloz/trial/colorrecipesexplorer/service/model/MixTypeJavaService.java index 7a5e050..92b72ef 100644 --- a/src/main/java/dev/fyloz/trial/colorrecipesexplorer/service/model/MixTypeJavaService.java +++ b/src/main/java/dev/fyloz/trial/colorrecipesexplorer/service/model/MixTypeJavaService.java @@ -66,7 +66,7 @@ public class MixTypeJavaService extends AbstractJavaService found = findOptional(repository.findByMaterial(material)); if (found.isEmpty()) - throw new EntityNotFoundException(type, ModelException.IdentifierType.OTHER, MixTypeKt.IDENTIFIER_MATERIAL_NAME, material); + throw new EntityNotFoundException(type, ModelException.IdentifierType.OTHER, material); return found.get(); } diff --git a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/ColorRecipesExplorerApplication.kt b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/ColorRecipesExplorerApplication.kt index 15b6483..4828d02 100644 --- a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/ColorRecipesExplorerApplication.kt +++ b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/ColorRecipesExplorerApplication.kt @@ -2,20 +2,15 @@ package dev.fyloz.trial.colorrecipesexplorer import dev.fyloz.trial.colorrecipesexplorer.config.properties.CREProperties import dev.fyloz.trial.colorrecipesexplorer.config.properties.MaterialTypeProperties -import org.slf4j.Logger import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration -import org.springframework.boot.context.properties.ConfigurationProperties import org.springframework.boot.context.properties.EnableConfigurationProperties -import org.springframework.boot.jdbc.DataSourceBuilder import org.springframework.boot.runApplication -import org.springframework.context.annotation.Bean -import javax.sql.DataSource @SpringBootApplication(exclude = [LiquibaseAutoConfiguration::class]) @EnableConfigurationProperties(MaterialTypeProperties::class, CREProperties::class, DatabaseUpdaterProperties::class) class ColorRecipesExplorerApplication -fun main(args: Array) { +fun main() { runApplication() } diff --git a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/config/WebSecurityConfig.kt b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/config/WebSecurityConfig.kt index 7f3e210..9863b35 100644 --- a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/config/WebSecurityConfig.kt +++ b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/config/WebSecurityConfig.kt @@ -189,9 +189,9 @@ const val defaultGroupCookieName = "Default-Group" val blacklistedJwtTokens = mutableListOf() class JwtAuthenticationFilter( - val authManager: AuthenticationManager, - val employeeService: EmployeeService, - val securityConfigurationProperties: SecurityConfigurationProperties + private val authManager: AuthenticationManager, + private val employeeService: EmployeeService, + private val securityConfigurationProperties: SecurityConfigurationProperties ) : UsernamePasswordAuthenticationFilter() { private var debugMode = false @@ -238,8 +238,8 @@ class JwtAuthenticationFilter( } class JwtAuthorizationFilter( - val userDetailsService: EmployeeUserDetailsServiceImpl, - val securityConfigurationProperties: SecurityConfigurationProperties, + private val userDetailsService: EmployeeUserDetailsServiceImpl, + private val securityConfigurationProperties: SecurityConfigurationProperties, authenticationManager: AuthenticationManager ) : BasicAuthenticationFilter(authenticationManager) { override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, chain: FilterChain) { diff --git a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/model/AccountModel.kt b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/model/AccountModel.kt index b54a862..d00cd6b 100644 --- a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/model/AccountModel.kt +++ b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/model/AccountModel.kt @@ -2,6 +2,7 @@ package dev.fyloz.trial.colorrecipesexplorer.model import com.fasterxml.jackson.annotation.JsonIgnore import com.fasterxml.jackson.annotation.JsonProperty +import dev.fyloz.trial.colorrecipesexplorer.model.validation.NullOrNotBlank import org.hibernate.annotations.Fetch import org.hibernate.annotations.FetchMode import org.springframework.security.core.GrantedAuthority @@ -109,18 +110,15 @@ open class EmployeeUpdateDto( @field:NotNull(message = EMPLOYEE_ID_NULL_MESSAGE) val id: Long, - @field:NotBlank(message = EMPLOYEE_FIRST_NAME_EMPTY_MESSAGE) - val firstName: String = "", + @field:NullOrNotBlank(message = EMPLOYEE_FIRST_NAME_EMPTY_MESSAGE) + val firstName: String?, - @field:NotBlank(message = EMPLOYEE_LAST_NAME_EMPTY_MESSAGE) - val lastName: String = "", + @field:NullOrNotBlank(message = EMPLOYEE_LAST_NAME_EMPTY_MESSAGE) + val lastName: String?, @Enumerated(EnumType.STRING) - val permissions: Set = mutableSetOf() -) : EntityDto { - override fun toEntity(): Employee = - Employee(id, firstName, lastName, permissions = permissions.toMutableSet()) -} + val permissions: Set? +) : EntityDto private const val GROUP_ID_NULL_MESSAGE = "Un identifiant est requis" @@ -148,6 +146,7 @@ data class EmployeeGroup( @JsonIgnore val employees: MutableSet = mutableSetOf() ) : NamedModel { + @JsonProperty("employeeCount") fun getEmployeeCount() = employees.size override fun equals(other: Any?): Boolean = other is EmployeeGroup && id == other.id && name == other.name @@ -313,16 +312,6 @@ fun employee( lastLoginTime ).apply(op) -fun employee( - employee: Employee, - newId: Long? = null -) = with(employee) { - Employee( - newId - ?: id, firstName, lastName, password, isDefaultGroupUser, isSystemUser, group, permissions, lastLoginTime - ) -} - fun employeeSaveDto( passwordEncoder: PasswordEncoder = BCryptPasswordEncoder(), id: Long = 0L, @@ -350,12 +339,6 @@ fun employeeGroup( op: EmployeeGroup.() -> Unit = {} ) = EmployeeGroup(id, name, permissions, employees).apply(op) -fun employeeGroup( - employeeGroup: EmployeeGroup, - newId: Long? = null, - newName: String? = null -) = with(employeeGroup) { EmployeeGroup(newId ?: id, newName ?: name, permissions, employees) } - fun employeeGroupSaveDto( name: String = "name", permissions: MutableSet = mutableSetOf(), diff --git a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/model/Material.kt b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/model/Material.kt index a32183e..bfcd908 100644 --- a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/model/Material.kt +++ b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/model/Material.kt @@ -9,7 +9,6 @@ import javax.persistence.* import javax.validation.constraints.Min import javax.validation.constraints.NotBlank import javax.validation.constraints.NotNull -import javax.validation.constraints.Size private const val MATERIAL_ID_NULL_MESSAGE = "Un identifiant est requis" private const val MATERIAL_NAME_NULL_MESSAGE = "Un nom est requis" @@ -98,6 +97,7 @@ data class InventoryMaterial( @NotNull val lowQuantity: Boolean = false ) +@Suppress("unused") fun Material.toInventoryMaterial(minimumQuantity: Float): InventoryMaterial { Assert.notNull(id, "Cannot convert a material without id to an inventory material") Assert.notNull(name, "Cannot convert a material without name to an inventory material") diff --git a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/model/Model.kt b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/model/Model.kt index 47795c7..825ad2b 100644 --- a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/model/Model.kt +++ b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/model/Model.kt @@ -11,7 +11,7 @@ interface NamedModel : Model { interface EntityDto { /** Converts the dto to an actual entity. */ - fun toEntity(): E + fun toEntity(): E { + throw UnsupportedOperationException() + } } - -fun Collection.sortedById(): Collection = this.sortedBy { it.id } diff --git a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/model/Recipe.kt b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/model/Recipe.kt index 353d1e9..4b904c1 100644 --- a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/model/Recipe.kt +++ b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/model/Recipe.kt @@ -50,6 +50,19 @@ data class Recipe( @OneToMany(cascade = [CascadeType.ALL], mappedBy = "recipe") var steps: MutableCollection ) : Model { + constructor() : this( + null, + "name", + "description", + 0, + null, + "remark", + "note", + company(), + mutableListOf(), + mutableListOf() + ) + constructor( id: Long, name: String, diff --git a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/model/RecipeStep.kt b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/model/RecipeStep.kt index 393fb21..80ccd59 100644 --- a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/model/RecipeStep.kt +++ b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/model/RecipeStep.kt @@ -1,10 +1,8 @@ package dev.fyloz.trial.colorrecipesexplorer.model import com.fasterxml.jackson.annotation.JsonIgnore -import dev.fyloz.trial.colorrecipesexplorer.model.validation.NullOrNotBlank import java.util.* import javax.persistence.* -import javax.validation.constraints.NotNull @Entity @Table(name = "recipe_step") diff --git a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/model/validation/NullOrNotBlank.kt b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/model/validation/NullOrNotBlank.kt index 3610ad5..ef262c6 100644 --- a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/model/validation/NullOrNotBlank.kt +++ b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/model/validation/NullOrNotBlank.kt @@ -3,7 +3,6 @@ package dev.fyloz.trial.colorrecipesexplorer.model.validation import javax.validation.Constraint import javax.validation.ConstraintValidator import javax.validation.ConstraintValidatorContext -import javax.validation.Payload import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract import kotlin.reflect.KClass @@ -15,8 +14,7 @@ private const val MESSAGE = "must be null or not blank" @Constraint(validatedBy = [NullOrNotBlankValidator::class]) annotation class NullOrNotBlank( val message: String = MESSAGE, - val groups: Array> = [], - val payload: Array> = [] + val groups: Array> = [] ) class NullOrNotBlankValidator : ConstraintValidator { @@ -42,5 +40,4 @@ fun isNotNullAndNotBlank(value: String?): Boolean { return value != null && value.isNotBlank() } -@ExperimentalContracts -fun String?.or(alternative: String): String = if (isNotNullAndNotBlank(this)) this else alternative +infix fun String?.or(alternative: String): String = if (isNotNullAndNotBlank(this)) this else alternative diff --git a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/model/validation/NullOrSize.kt b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/model/validation/NullOrSize.kt index 192960f..cfcb7d7 100644 --- a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/model/validation/NullOrSize.kt +++ b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/model/validation/NullOrSize.kt @@ -3,7 +3,6 @@ package dev.fyloz.trial.colorrecipesexplorer.model.validation import javax.validation.Constraint import javax.validation.ConstraintValidator import javax.validation.ConstraintValidatorContext -import javax.validation.Payload import kotlin.reflect.KClass private const val MIN_SIZE = Long.MIN_VALUE @@ -17,8 +16,7 @@ annotation class NullOrSize( val min: Long = MIN_SIZE, val max: Long = MAX_SIZE, val message: String = MESSAGE, - val groups: Array> = [], - val payload: Array> = [] + val groups: Array> = [] ) class NullOrSizeValidator : ConstraintValidator { diff --git a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/rest/InventoryController.kt b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/rest/InventoryController.kt index b6638ec..eae95da 100644 --- a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/rest/InventoryController.kt +++ b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/rest/InventoryController.kt @@ -1,5 +1,5 @@ -//package dev.fyloz.trial.colorrecipesexplorer.rest -// +package dev.fyloz.trial.colorrecipesexplorer.rest + //import dev.fyloz.trial.colorrecipesexplorer.model.InventoryMaterial //import dev.fyloz.trial.colorrecipesexplorer.service.InventoryService //import org.springframework.http.ResponseEntity diff --git a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/rest/RestApiController.kt b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/rest/RestApiController.kt index a45fa05..9c4392e 100644 --- a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/rest/RestApiController.kt +++ b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/rest/RestApiController.kt @@ -34,7 +34,7 @@ interface RestModelApiController, U : EntityDto> abstract class AbstractRestApiController, U : EntityDto, S : ExternalService>( val service: S, - protected val controllerPath: String + private val controllerPath: String ) : RestApiController { protected abstract fun getEntityId(entity: E): Any? diff --git a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/AccountService.kt b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/AccountService.kt index 8200393..8240d29 100644 --- a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/AccountService.kt +++ b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/AccountService.kt @@ -1,12 +1,12 @@ package dev.fyloz.trial.colorrecipesexplorer.service -import dev.fyloz.trial.colorrecipesexplorer.config.SecurityConfigurationProperties import dev.fyloz.trial.colorrecipesexplorer.config.blacklistedJwtTokens import dev.fyloz.trial.colorrecipesexplorer.config.defaultGroupCookieName import dev.fyloz.trial.colorrecipesexplorer.exception.model.EntityAlreadyExistsRestException import dev.fyloz.trial.colorrecipesexplorer.exception.model.EntityNotFoundException import dev.fyloz.trial.colorrecipesexplorer.exception.model.EntityNotFoundRestException import dev.fyloz.trial.colorrecipesexplorer.model.* +import dev.fyloz.trial.colorrecipesexplorer.model.validation.or import dev.fyloz.trial.colorrecipesexplorer.repository.EmployeeGroupRepository import dev.fyloz.trial.colorrecipesexplorer.repository.EmployeeRepository import org.springframework.beans.factory.annotation.Autowired @@ -170,13 +170,13 @@ class EmployeeServiceImpl(employeeRepository: EmployeeRepository, val passwordEn return update(with(entity) { Employee( id = id, - firstName = if (firstName.isNotBlank()) firstName else persistedEmployee.firstName, - lastName = if (lastName.isNotBlank()) lastName else persistedEmployee.lastName, + firstName = firstName or persistedEmployee.firstName, + lastName = lastName or persistedEmployee.lastName, password = persistedEmployee.password, isDefaultGroupUser = false, isSystemUser = false, group = persistedEmployee.group, - permissions = if (permissions.isNotEmpty()) permissions.toMutableSet() else persistedEmployee.permissions, + permissions = permissions?.toMutableSet() ?: persistedEmployee.permissions, lastLoginTime = persistedEmployee.lastLoginTime ) }) diff --git a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/InventoryService.kt b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/InventoryService.kt index 95b45d7..28c8888 100644 --- a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/InventoryService.kt +++ b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/InventoryService.kt @@ -1,20 +1,12 @@ package dev.fyloz.trial.colorrecipesexplorer.service import dev.fyloz.trial.colorrecipesexplorer.exception.TooLowQuantityException -import dev.fyloz.trial.colorrecipesexplorer.model.InventoryMaterial import dev.fyloz.trial.colorrecipesexplorer.model.Material import dev.fyloz.trial.colorrecipesexplorer.model.dto.InventoryDto -import dev.fyloz.trial.colorrecipesexplorer.model.toInventoryMaterial import org.springframework.stereotype.Service -const val minimumQuantity = 100.0f // TODO quantity stored in database - @Service class InventoryService(val materialService: MaterialService) { - fun getAllMaterials(): Collection { - return materialService.getAllNotMixType().map { it.toInventoryMaterial(minimumQuantity) } - } - /** * Use all materials in the given [mixes]. * @throws TooLowQuantityException When there is not enough stock for a material diff --git a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MaterialTypeService.kt b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MaterialTypeService.kt index b4d36b2..81a4bc2 100644 --- a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MaterialTypeService.kt +++ b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/MaterialTypeService.kt @@ -105,8 +105,7 @@ class MaterialTypeServiceImpl(repository: MaterialTypeRepository, private val ma } @ResponseStatus(HttpStatus.CONFLICT) -class CannotDeleteUsedMaterialTypeRestException : RestException(HttpStatus.CONFLICT) { - override val exceptionMessage: String = "Cannot delete a used material type" - +class CannotDeleteUsedMaterialTypeRestException : + RestException("Cannot delete a used material type", HttpStatus.CONFLICT) { override fun buildBody(): RestExceptionBody = object : RestExceptionBody() {} } diff --git a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/RecipeService.kt b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/RecipeService.kt index 27ce618..210d7f4 100644 --- a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/RecipeService.kt +++ b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/RecipeService.kt @@ -19,7 +19,7 @@ interface RecipeService : ExternalModelService - /** Updates the public data of a recipe with the given [publicDateDto]. */ + /** Updates the public data of a recipe with the given [publicDataDto]. */ fun updatePublicData(publicDataDto: RecipePublicDataDto) /** Adds the given [mix] to the given [recipe]. */ diff --git a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/Service.kt b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/Service.kt index c916344..1c6fc82 100644 --- a/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/Service.kt +++ b/src/main/kotlin/dev/fyloz/trial/colorrecipesexplorer/service/Service.kt @@ -11,7 +11,6 @@ import dev.fyloz.trial.colorrecipesexplorer.rest.RestApiController import io.jsonwebtoken.lang.Assert import org.springframework.data.jpa.repository.JpaRepository import org.springframework.data.repository.findByIdOrNull -import kotlin.contracts.ExperimentalContracts /** * A service implementing the basics CRUD operations for the given entities. @@ -144,6 +143,7 @@ interface ExternalNamedModelService, U : Entity NamedModelService, ExternalModelService /** An [AbstractService] with the functionalities of a [ExternalService]. */ +@Suppress("unused") abstract class AbstractExternalService, U : EntityDto, R : JpaRepository>(repository: R) : AbstractService(repository), ExternalService diff --git a/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/repository/RecipeStepRepositoryTest.kt b/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/repository/RecipeStepRepositoryTest.kt index 3bdd741..7d05f58 100644 --- a/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/repository/RecipeStepRepositoryTest.kt +++ b/src/test/kotlin/dev/fyloz/trial/colorrecipesexplorer/repository/RecipeStepRepositoryTest.kt @@ -5,6 +5,7 @@ import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager +@Suppress("UNUSED_PARAMETER") @Disabled @DataJpaTest class RecipeStepRepositoryTest @Autowired constructor(