diff --git a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/dtos/account/UserDto.kt b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/dtos/account/UserDto.kt index 6216a76..0c94b1a 100644 --- a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/dtos/account/UserDto.kt +++ b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/dtos/account/UserDto.kt @@ -48,9 +48,7 @@ data class UserSaveDto( val permissions: List, - @field:JsonIgnore val isSystemUser: Boolean = false, - - @field:JsonIgnore val isDefaultGroupUser: Boolean = false + @field:JsonIgnore val isSystemUser: Boolean = false ) data class UserUpdateDto( diff --git a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/GroupTokenLogic.kt b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/GroupTokenLogic.kt index f689530..3350224 100644 --- a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/GroupTokenLogic.kt +++ b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/GroupTokenLogic.kt @@ -10,6 +10,7 @@ import dev.fyloz.colorrecipesexplorer.logic.BaseLogic import dev.fyloz.colorrecipesexplorer.service.account.GroupTokenService import java.util.* import javax.annotation.PostConstruct +import kotlin.collections.HashSet interface GroupTokenLogic { fun isDisabled(id: String): Boolean @@ -23,13 +24,15 @@ interface GroupTokenLogic { } @LogicComponent -class DefaultGroupTokenLogic(private val service: GroupTokenService, private val groupLogic: GroupLogic) : +class DefaultGroupTokenLogic( + private val service: GroupTokenService, + private val groupLogic: GroupLogic, + private val enabledTokensCache: HashSet = hashSetOf() // In constructor for unit testing +) : GroupTokenLogic { private val typeName = Constants.ModelNames.GROUP_TOKEN private val typeNameLowerCase = typeName.lowercase() - private val enabledTokensCache = hashSetOf() - @PostConstruct fun initEnabledTokensCache() { val tokensIds = getAll().filter { it.enabled }.map { it.id.toString() } @@ -45,8 +48,10 @@ class DefaultGroupTokenLogic(private val service: GroupTokenService, private val override fun save(dto: GroupTokenSaveDto): GroupTokenDto { throwIfNameAlreadyExists(dto.name) + // We don't need to check for collision, because UUIDs with different names will be different + val id = generateUUIDForName(dto.name) val token = GroupTokenDto( - generateUniqueUUIDForName(dto.name), dto.name, true, groupLogic.getById(dto.groupId) + id, dto.name, true, groupLogic.getById(dto.groupId) ) val savedToken = service.save(token) @@ -56,11 +61,15 @@ class DefaultGroupTokenLogic(private val service: GroupTokenService, private val } override fun enable(id: String) = setEnabled(id, true).also { - enabledTokensCache.add(id) + if (isDisabled(id)) { + enabledTokensCache.add(id) + } } override fun disable(id: String) = setEnabled(id, false).also { - enabledTokensCache.remove(id) + if (!isDisabled(id)) { + enabledTokensCache.remove(id) + } } override fun deleteById(id: String) { @@ -72,17 +81,6 @@ class DefaultGroupTokenLogic(private val service: GroupTokenService, private val service.save(this.copy(enabled = enabled)) } - private fun generateUniqueUUIDForName(name: String): UUID { - var id = generateUUIDForName(name) - - // UUIDs do not guarantee that collisions can't happen - while (service.existsById(id)) { - id = generateUUIDForName(name) - } - - return id - } - private fun generateUUIDForName(name: String) = UUID.nameUUIDFromBytes(name.toByteArray()) private fun throwIfNameAlreadyExists(name: String) { diff --git a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/JwtLogic.kt b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/JwtLogic.kt index 4b0a971..1cda7b1 100644 --- a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/JwtLogic.kt +++ b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/JwtLogic.kt @@ -15,8 +15,6 @@ import org.springframework.stereotype.Service import java.time.Instant import java.util.* -const val jwtClaimUser = "user" - interface JwtLogic { /** Build a JWT for the given [userDetails]. */ fun buildUserJwt(userDetails: UserDetails): String diff --git a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/service/account/UserService.kt b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/service/account/UserService.kt index 08a6c26..299128d 100644 --- a/src/main/kotlin/dev/fyloz/colorrecipesexplorer/service/account/UserService.kt +++ b/src/main/kotlin/dev/fyloz/colorrecipesexplorer/service/account/UserService.kt @@ -86,6 +86,6 @@ class DefaultUserService(repository: UserRepository, private val groupService: G return perms + groupService.flattenPermissions(user.group) } - return perms + return perms.distinctBy { it.id } } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 8a271b9..18c7f3f 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -30,4 +30,4 @@ spring.jackson.deserialization.fail-on-null-for-primitives=true spring.jackson.default-property-inclusion=non_null spring.profiles.active=@spring.profiles.active@ -spring.sql.init.continue-on-error=true \ No newline at end of file +spring.sql.init.continue-on-error=true diff --git a/src/test/kotlin/dev/fyloz/colorrecipesexplorer/logic/DefaultJwtLogicTest.kt b/src/test/kotlin/dev/fyloz/colorrecipesexplorer/logic/DefaultJwtLogicTest.kt index 08d784c..37e98ff 100644 --- a/src/test/kotlin/dev/fyloz/colorrecipesexplorer/logic/DefaultJwtLogicTest.kt +++ b/src/test/kotlin/dev/fyloz/colorrecipesexplorer/logic/DefaultJwtLogicTest.kt @@ -1,100 +1,122 @@ package dev.fyloz.colorrecipesexplorer.logic import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper -import com.fasterxml.jackson.module.kotlin.readValue import dev.fyloz.colorrecipesexplorer.config.properties.CreSecurityProperties import dev.fyloz.colorrecipesexplorer.dtos.account.UserDetails import dev.fyloz.colorrecipesexplorer.dtos.account.UserDto import dev.fyloz.colorrecipesexplorer.logic.account.DefaultJwtLogic -import dev.fyloz.colorrecipesexplorer.logic.account.jwtClaimUser -import dev.fyloz.colorrecipesexplorer.utils.base64encode -import dev.fyloz.colorrecipesexplorer.utils.isAround -import io.jsonwebtoken.Jwts -import io.jsonwebtoken.jackson.io.JacksonDeserializer +import dev.fyloz.colorrecipesexplorer.model.account.Permission import io.mockk.clearAllMocks import io.mockk.spyk import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Test -import java.time.Instant +import java.util.* import kotlin.test.assertEquals -import kotlin.test.assertTrue +import kotlin.test.assertFalse class DefaultJwtLogicTest { private val objectMapper = jacksonObjectMapper() private val securityProperties = CreSecurityProperties().apply { - jwtSecret = "XRRm7OflmFuCrOB2Xvmfsercih9DCKom" + jwtSecret = "exBwMbD9Jw7YF7HYpwXQjcsPf4SrRSSF5YTvgbj0" jwtDuration = 1000000L } - private val jwtParser by lazy { - Jwts.parserBuilder() - .deserializeJsonWith(JacksonDeserializer>(objectMapper)) - .setSigningKey(securityProperties.jwtSecret.base64encode()) - .build() - } - private val jwtService = spyk(DefaultJwtLogic(objectMapper, securityProperties)) + private val jwtLogic = spyk(DefaultJwtLogic(objectMapper, securityProperties)) - private val user = UserDto(0L, "Unit test", "User", "", null, listOf()) + private val permissions = listOf(Permission.VIEW_RECIPES, Permission.READ_FILE, Permission.VIEW_CATALOG) + private val user = UserDto(999L, "Unit test", "User", "", null, permissions) + private val userDetails = UserDetails(user) + + private val userJwt = "eyJhbGciOiJIUzM4NCJ9.eyJzdWIiOiI5OTkiLCJleHAiOjE2Njk2MTc1MDcsInBlcm1zIjoiWzIsMCwzXSIsInR5cGUiOjB9.bg8hbTRsWOcx4te3L0vi8WNPXWLZO-heS7bNsO_FBpkRPy4l-MtdLOa6hx_-pXbZ" + private val groupTokenJwt = "eyJhbGciOiJIUzM4NCJ9.eyJzdWIiOiJhMDIyZWU3YS03NGY5LTNjYTYtYmYwZC04ZTg3OWE2NjRhOWUifQ.VaRqPJ30h8WUACPf8wVrjaxINQcc9xnbzGOcMesW_PbeN9rEGzgkgFEuV4TRGlOr" + private val groupTokenId = UUID.nameUUIDFromBytes("Unit test token".toByteArray()) @AfterEach internal fun afterEach() { clearAllMocks() } - private fun withParsedUserOutputDto(jwt: String, test: (UserDto) -> Unit) { - val serializedUser = jwtParser.parseClaimsJws(jwt) - .body.get(jwtClaimUser, String::class.java) + @Test + fun buildUserJwt_normalBehavior_buildJwtWithValidSubject() { + // Arrange + // Act + val jwt = jwtLogic.buildUserJwt(userDetails) - test(objectMapper.readValue(serializedUser)) + // Assert + val parsedJwt = jwtLogic.parseUserJwt(jwt) + assertEquals(user.id.toString(), parsedJwt.id) } @Test - fun buildJwt_userDetails_normalBehavior_returnsJwtStringWithValidUser() { - val userDetails = UserDetails(user) + fun buildUserJwt_normalBehavior_buildJwtWithValidType() { + // Arrange + // Act + val jwt = jwtLogic.buildUserJwt(userDetails) - val builtJwt = jwtService.buildUserJwt(userDetails) - - withParsedUserOutputDto(builtJwt) { parsedUser -> - assertEquals(user, parsedUser) - } + // Assert + val parsedJwt = jwtLogic.parseUserJwt(jwt) + assertFalse(parsedJwt.isGroup) } @Test - fun buildJwt_user_normalBehavior_returnsJwtStringWithValidUser() { - val builtJwt = jwtService.buildUserJwt(user) + fun buildUserJwt_normalBehavior_buildJwtWithValidPermissions() { + // Arrange + // Act + val jwt = jwtLogic.buildUserJwt(userDetails) - withParsedUserOutputDto(builtJwt) { parsedUser -> - assertEquals(user, parsedUser) - } + // Assert + val parsedJwt = jwtLogic.parseUserJwt(jwt) + assertEquals(userDetails.authorities, parsedJwt.authorities) } @Test - fun buildJwt_user_normalBehavior_returnsJwtStringWithValidSubject() { - val builtJwt = jwtService.buildUserJwt(user) - val jwtSubject = jwtParser.parseClaimsJws(builtJwt).body.subject + fun buildGroupTokenIdJwt_normalBehavior_buildJwtWithValidSubject(){ + // Arrange + // Act + val jwt = jwtLogic.buildGroupTokenIdJwt(groupTokenId) - assertEquals(user.id.toString(), jwtSubject) + // Assert + val parsedGroupId = jwtLogic.parseGroupTokenIdJwt(jwt) + assertEquals(groupTokenId, parsedGroupId) } @Test - fun buildJwt_user_returnsJwtWithValidExpirationDate() { - val jwtExpectedExpirationDate = Instant.now().plusSeconds(securityProperties.jwtDuration) + fun parseUserJwt_normalBehavior_returnsUserWithValidId() { + // Arrange + // Act + val user = jwtLogic.parseUserJwt(userJwt) - val builtJwt = jwtService.buildUserJwt(user) - val jwtExpiration = jwtParser.parseClaimsJws(builtJwt) - .body.expiration.toInstant() - - // Check if it's between 1 second - assertTrue { jwtExpiration.isAround(jwtExpectedExpirationDate) } + // Assert + assertEquals(userDetails.id, user.id) } - // parseJwt() + @Test + fun parseUserJwt_normalBehavior_returnsUserWithValidType() { + // Arrange + // Act + val user = jwtLogic.parseUserJwt(userJwt) + + // Assert + assertFalse(user.isGroup) + } @Test - fun parseJwt_normalBehavior_returnsExpectedUser() { - val jwt = jwtService.buildUserJwt(user) - val parsedUser = jwtService.parseUserJwt(jwt) + fun parseUserJwt_normalBehavior_returnsUserWithValidPermissions() { + // Arrange + // Act + val user = jwtLogic.parseUserJwt(userJwt) - assertEquals(user, parsedUser) + // Assert + assertEquals(userDetails.authorities, user.authorities) + } + + @Test + fun parseGroupTokenId_normalBehavior_returnsValidGroupTokenId() { + // Arrange + // Act + val parsedGroupTokenId = jwtLogic.parseGroupTokenIdJwt(groupTokenJwt) + + // Assert + assertEquals(groupTokenId, parsedGroupTokenId) } } diff --git a/src/test/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/DefaultGroupLogicTest.kt b/src/test/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/DefaultGroupLogicTest.kt index 2c9ea17..83d3a3e 100644 --- a/src/test/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/DefaultGroupLogicTest.kt +++ b/src/test/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/DefaultGroupLogicTest.kt @@ -23,8 +23,7 @@ class DefaultGroupLogicTest { } private val userLogicMock = mockk { every { getAllByGroup(any()) } returns listOf() - every { getById(any(), any(), any()) } returns user - every { getDefaultGroupUser(any()) } returns user + every { getById(any(), any()) } returns user every { deleteById(any()) } just runs } @@ -69,16 +68,4 @@ class DefaultGroupLogicTest { // Assert assertThrows { groupLogic.update(group) } } - - @Test - fun deleteById_normalBehavior_callsDeleteByIdInUserLogicWithDefaultGroupUserId() { - // Arrange - // Act - groupLogic.deleteById(group.id) - - // Assert - verify { - userLogicMock.deleteById(group.defaultGroupUserId) - } - } } diff --git a/src/test/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/DefaultGroupTokenLogicTest.kt b/src/test/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/DefaultGroupTokenLogicTest.kt new file mode 100644 index 0000000..25f8182 --- /dev/null +++ b/src/test/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/DefaultGroupTokenLogicTest.kt @@ -0,0 +1,234 @@ +package dev.fyloz.colorrecipesexplorer.logic.account + +import dev.fyloz.colorrecipesexplorer.dtos.account.GroupDto +import dev.fyloz.colorrecipesexplorer.dtos.account.GroupTokenDto +import dev.fyloz.colorrecipesexplorer.dtos.account.GroupTokenSaveDto +import dev.fyloz.colorrecipesexplorer.exception.AlreadyExistsException +import dev.fyloz.colorrecipesexplorer.exception.NotFoundException +import dev.fyloz.colorrecipesexplorer.service.account.GroupTokenService +import io.mockk.* +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import java.util.* +import kotlin.test.* + +class DefaultGroupTokenLogicTest { + private val groupTokenServiceMock = mockk() + private val groupLogicMock = mockk() + + private val enabledTokenCache = hashSetOf() + + private val groupTokenLogic = spyk(DefaultGroupTokenLogic(groupTokenServiceMock, groupLogicMock, enabledTokenCache)) + + private val groupTokenName = "Unit test token" + private val groupTokenId = UUID.nameUUIDFromBytes(groupTokenName.toByteArray()) + private val groupTokenIdStr = groupTokenId.toString() + private val group = GroupDto(1L, "Unit test group", listOf(), listOf()) + private val groupToken = GroupTokenDto(groupTokenId, groupTokenName, true, group) + private val groupTokenSaveDto = GroupTokenSaveDto(groupTokenName, group.id) + + @AfterEach + fun afterEach() { + clearAllMocks() + enabledTokenCache.clear() + } + + @Test + fun isDisabled_groupTokenIdInCache_returnsFalse() { + // Arrange + enabledTokenCache.add(groupTokenIdStr) + + // Act + val disabled = groupTokenLogic.isDisabled(groupTokenIdStr) + + // Assert + assertFalse(disabled) + } + + @Test + fun isDisabled_groupTokenIdNotInCache_returnsTrue() { + // Arrange + // Act + val disabled = groupTokenLogic.isDisabled(groupTokenIdStr) + + // Assert + assertTrue(disabled) + } + + @Test + fun getAll_normalBehavior_returnsFromService() { + // Arrange + val expectedGroupTokens = listOf(groupToken) + + every { groupTokenServiceMock.getAll() } returns expectedGroupTokens + + // Act + val actualGroupTokens = groupTokenLogic.getAll() + + // Assert + assertEquals(expectedGroupTokens, actualGroupTokens) + } + + @Test + fun getById_string_normalBehavior_callsGetByIdWithValidUUID() { + // Arrange + every { groupTokenLogic.getById(any()) } returns groupToken + + // Act + groupTokenLogic.getById(groupTokenIdStr) + + // Assert + verify { + groupTokenLogic.getById(groupTokenId) + } + } + + @Test + fun getById_uuid_normalBehavior_returnsFromService() { + // Arrange + every { groupTokenServiceMock.getById(any()) } returns groupToken + + // Act + val actualGroupToken = groupTokenLogic.getById(groupTokenId) + + // Assert + assertSame(groupToken, actualGroupToken) + } + + @Test + fun getById_uuid_notFound_throwsNotFoundException() { + // Arrange + every { groupTokenServiceMock.getById(any()) } returns null + + // Act + // Assert + assertThrows { groupTokenLogic.getById(groupTokenId) } + } + + @Test + fun save_normalBehavior_callsSaveInService() { + // Arrange + every { groupTokenServiceMock.existsByName(any()) } returns false + every { groupTokenServiceMock.save(any()) } returns groupToken + every { groupLogicMock.getById(any()) } returns group + + // Act + groupTokenLogic.save(groupTokenSaveDto) + + // Assert + verify { + groupTokenServiceMock.save(groupToken) + } + } + + @Test + fun save_normalBehavior_addsIdToEnabledTokensCache() { + // Arrange + every { groupTokenServiceMock.existsByName(any()) } returns false + every { groupTokenServiceMock.save(any()) } returns groupToken + every { groupLogicMock.getById(any()) } returns group + + // Act + groupTokenLogic.save(groupTokenSaveDto) + + // Assert + assertContains(enabledTokenCache, groupTokenIdStr) + } + + @Test + fun save_nameAlreadyExists_throwsAlreadyExistsException() { + // Arrange + every { groupTokenServiceMock.existsByName(any()) } returns true + + // Act + // Assert + assertThrows { groupTokenLogic.save(groupTokenSaveDto) } + } + + @Test + fun enable_normalBehavior_savesTokenInService() { + // Arrange + every { groupTokenServiceMock.save(any()) } returns groupToken + every { groupTokenLogic.getById(any()) } returns groupToken + + // Act + groupTokenLogic.enable(groupTokenIdStr) + + // Assert + verify { + groupTokenServiceMock.save(match { + it.id == groupTokenId && it.name == groupTokenName && it.enabled + }) + } + } + + @Test + fun enable_normalBehavior_addsIdToEnabledTokensCache() { + // Arrange + every { groupTokenServiceMock.save(any()) } returns groupToken + every { groupTokenLogic.getById(any()) } returns groupToken + + // Act + groupTokenLogic.enable(groupTokenIdStr) + + // Assert + assertContains(enabledTokenCache, groupTokenIdStr) + } + + @Test + fun disable_normalBehavior_savesTokenInService() { + // Arrange + every { groupTokenServiceMock.save(any()) } returns groupToken + every { groupTokenLogic.getById(any()) } returns groupToken + + // Act + groupTokenLogic.disable(groupTokenIdStr) + + // Assert + verify { + groupTokenServiceMock.save(match { + it.id == groupTokenId && it.name == groupTokenName && !it.enabled + }) + } + } + + @Test + fun disable_normalBehavior_removesIdFromEnabledTokensCache() { + // Arrange + every { groupTokenServiceMock.save(any()) } returns groupToken + every { groupTokenLogic.getById(any()) } returns groupToken + + // Act + groupTokenLogic.disable(groupTokenIdStr) + + // Assert + assertFalse(enabledTokenCache.contains(groupTokenIdStr)) + } + + @Test + fun deleteById_normalBehavior_callsService() { + // Arrange + every { groupTokenServiceMock.deleteById(any()) } just runs + + // Act + groupTokenLogic.deleteById(groupTokenIdStr) + + // Assert + verify { + groupTokenServiceMock.deleteById(groupTokenId) + } + } + + @Test + fun deleteById_normalBehavior_removesIdFromEnabledTokensCache() { + // Arrange + every { groupTokenServiceMock.deleteById(any()) } just runs + + // Act + groupTokenLogic.deleteById(groupTokenIdStr) + + // Assert + assertFalse(enabledTokenCache.contains(groupTokenIdStr)) + } +} diff --git a/src/test/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/DefaultUserLogicTest.kt b/src/test/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/DefaultUserLogicTest.kt index d288021..9e6dc89 100644 --- a/src/test/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/DefaultUserLogicTest.kt +++ b/src/test/kotlin/dev/fyloz/colorrecipesexplorer/logic/account/DefaultUserLogicTest.kt @@ -22,11 +22,10 @@ class DefaultUserLogicTest { private val userServiceMock = mockk { every { existsById(any()) } returns false every { existsByFirstNameAndLastName(any(), any(), any()) } returns false - every { getAll(any(), any()) } returns listOf() + every { getAll(any()) } returns listOf() every { getAllByGroup(any()) } returns listOf() - every { getById(any(), any(), any()) } returns user + every { getById(any(), any()) } returns user every { getByFirstNameAndLastName(any(), any()) } returns user - every { getDefaultGroupUser(any()) } returns user } private val groupLogicMock = mockk { every { getById(any()) } returns group @@ -44,8 +43,7 @@ class DefaultUserLogicTest { user.password, null, user.permissions, - user.isSystemUser, - user.isDefaultGroupUser + user.isSystemUser ) private val userUpdateDto = UserUpdateDto(user.id, user.firstName, user.lastName, null, listOf()) @@ -62,7 +60,7 @@ class DefaultUserLogicTest { // Assert verify { - userServiceMock.getAll(isSystemUser = false, isDefaultGroupUser = false) + userServiceMock.getAll(isSystemUser = false) } confirmVerified(userServiceMock) } @@ -88,7 +86,7 @@ class DefaultUserLogicTest { // Assert verify { - userLogic.getById(user.id, isSystemUser = false, isDefaultGroupUser = false) + userLogic.getById(user.id, isSystemUser = false) } } @@ -96,11 +94,11 @@ class DefaultUserLogicTest { fun getById_normalBehavior_callsGetByIdInService() { // Arrange // Act - userLogic.getById(user.id, isSystemUser = false, isDefaultGroupUser = true) + userLogic.getById(user.id, isSystemUser = false) // Assert verify { - userServiceMock.getById(user.id, isSystemUser = false, isDefaultGroupUser = true) + userServiceMock.getById(user.id, isSystemUser = false) } confirmVerified(userServiceMock) } @@ -108,54 +106,13 @@ class DefaultUserLogicTest { @Test fun getById_notFound_throwsNotFoundException() { // Arrange - every { userServiceMock.getById(any(), any(), any()) } returns null + every { userServiceMock.getById(any(), any()) } returns null // Act // Assert assertThrows { userLogic.getById(user.id) } } - @Test - fun getDefaultGroupUser_normalBehavior_callsGetDefaultGroupUserInService() { - // Arrange - // Act - userLogic.getDefaultGroupUser(group) - - // Assert - verify { - userServiceMock.getDefaultGroupUser(group) - } - confirmVerified(userServiceMock) - } - - @Test - fun getDefaultGroupUser_notFound_throwsNotFoundException() { - // Arrange - every { userServiceMock.getDefaultGroupUser(any()) } returns null - - // Act - // Assert - assertThrows { userLogic.getDefaultGroupUser(group) } - } - - @Test - fun saveDefaultGroupUser_normalBehavior_callsSaveWithValidSaveDto() { - // Arrange - every { userLogic.save(any()) } returns user - - val expectedSaveDto = UserSaveDto( - group.defaultGroupUserId, group.name, "User", group.name, group.id, listOf(), isDefaultGroupUser = true - ) - - // Act - userLogic.saveDefaultGroupUser(group) - - // Assert - verify { - userLogic.save(expectedSaveDto) - } - } - @Test fun save_dto_normalBehavior_callsSaveWithValidUser() { // Arrange @@ -208,7 +165,7 @@ class DefaultUserLogicTest { @Test fun update_dto_normalBehavior_callsUpdateWithValidUser() { // Arrange - every { userLogic.getById(any(), any(), any()) } returns user + every { userLogic.getById(any(), any()) } returns user every { userLogic.update(any()) } returns user // Act