From 0ff0f4e9fc5210cf10bc483a5fe40d258b4830e9 Mon Sep 17 00:00:00 2001 From: pricelees Date: Sun, 12 Oct 2025 14:01:27 +0900 Subject: [PATCH] =?UTF-8?q?refactor:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EC=9D=B8=ED=95=9C=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sangdol/roomescape/auth/AuthApiTest.kt | 74 +++++++++++++++---- .../auth/FailOnSaveLoginHistoryTest.kt | 64 ---------------- 2 files changed, 58 insertions(+), 80 deletions(-) delete mode 100644 service/src/test/kotlin/com/sangdol/roomescape/auth/FailOnSaveLoginHistoryTest.kt diff --git a/service/src/test/kotlin/com/sangdol/roomescape/auth/AuthApiTest.kt b/service/src/test/kotlin/com/sangdol/roomescape/auth/AuthApiTest.kt index 7e9eae99..1cdc6694 100644 --- a/service/src/test/kotlin/com/sangdol/roomescape/auth/AuthApiTest.kt +++ b/service/src/test/kotlin/com/sangdol/roomescape/auth/AuthApiTest.kt @@ -1,16 +1,18 @@ package com.sangdol.roomescape.auth +import com.ninjasquad.springmockk.MockkBean import com.ninjasquad.springmockk.SpykBean import com.sangdol.common.types.web.HttpStatus import com.sangdol.roomescape.admin.exception.AdminErrorCode import com.sangdol.roomescape.auth.business.CLAIM_ADMIN_TYPE_KEY import com.sangdol.roomescape.auth.business.CLAIM_PERMISSION_KEY import com.sangdol.roomescape.auth.business.CLAIM_STORE_ID_KEY +import com.sangdol.roomescape.auth.business.LoginHistoryEventListener +import com.sangdol.roomescape.auth.business.domain.LoginHistoryEvent +import com.sangdol.roomescape.auth.business.domain.PrincipalType +import com.sangdol.roomescape.auth.dto.LoginRequest import com.sangdol.roomescape.auth.exception.AuthErrorCode import com.sangdol.roomescape.auth.infrastructure.jwt.JwtUtils -import com.sangdol.roomescape.auth.infrastructure.persistence.LoginHistoryRepository -import com.sangdol.roomescape.auth.dto.LoginRequest -import com.sangdol.roomescape.auth.business.domain.PrincipalType import com.sangdol.roomescape.supports.AdminFixture import com.sangdol.roomescape.supports.FunSpecSpringbootTest import com.sangdol.roomescape.supports.UserFixture @@ -18,19 +20,31 @@ import com.sangdol.roomescape.supports.runTest import com.sangdol.roomescape.user.exception.UserErrorCode import com.sangdol.roomescape.user.infrastructure.persistence.UserEntity import io.kotest.assertions.assertSoftly -import io.kotest.matchers.collections.shouldHaveSize import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldNotBe -import io.mockk.every +import io.mockk.* import io.restassured.response.ValidatableResponse import org.hamcrest.CoreMatchers.equalTo class AuthApiTest( @SpykBean private val jwtUtils: JwtUtils, - private val loginHistoryRepository: LoginHistoryRepository + @MockkBean(relaxed = true) private val loginHistoryEventListener: LoginHistoryEventListener, ) : FunSpecSpringbootTest() { + lateinit var slot: CapturingSlot + init { + beforeTest { + slot = slot() + every { + loginHistoryEventListener.onLoginCompleted(capture(slot)) + } just Runs + } + + afterTest { + clearMocks(jwtUtils, loginHistoryEventListener) + } + context("로그인을 시도한다.") { context("성공 응답") { listOf( @@ -64,6 +78,7 @@ class AuthApiTest( password = user.password, type = PrincipalType.USER, ) { + val token: String = it.extract().path("data.accessToken") jwtUtils.extractSubject(token) shouldBe user.id.toString() } @@ -71,6 +86,16 @@ class AuthApiTest( } context("실패 응답") { + + lateinit var slot: CapturingSlot + + beforeTest { + slot = slot() + every { + loginHistoryEventListener.onLoginCompleted(capture(slot)) + } just Runs + } + context("계정이 맞으면 로그인 실패 이력을 남긴다.") { test("비밀번호가 틀린 경우") { val admin = testAuthUtil.createAdmin(AdminFixture.default) @@ -88,9 +113,14 @@ class AuthApiTest( body("code", equalTo(AuthErrorCode.LOGIN_FAILED.errorCode)) } ).also { - assertSoftly(loginHistoryRepository.findByPrincipalId(admin.id)[0]) { + verify(exactly = 1) { + loginHistoryEventListener.onLoginCompleted(any()) + } + + assertSoftly(slot.captured) { + this.id shouldBe admin.id + this.type shouldBe PrincipalType.ADMIN this.success shouldBe false - this.principalType shouldBe PrincipalType.ADMIN } } } @@ -115,9 +145,14 @@ class AuthApiTest( body("code", equalTo(AuthErrorCode.TEMPORARY_AUTH_ERROR.errorCode)) } ).also { - assertSoftly(loginHistoryRepository.findByPrincipalId(admin.id)[0]) { + verify(exactly = 1) { + loginHistoryEventListener.onLoginCompleted(any()) + } + + assertSoftly(slot.captured) { + this.id shouldBe admin.id + this.type shouldBe PrincipalType.ADMIN this.success shouldBe false - this.principalType shouldBe PrincipalType.ADMIN } } } @@ -144,7 +179,9 @@ class AuthApiTest( body("code", equalTo(UserErrorCode.USER_NOT_FOUND.errorCode)) } ).also { - loginHistoryRepository.findAll() shouldHaveSize 0 + verify(exactly = 0) { + loginHistoryEventListener.onLoginCompleted(any()) + } } } @@ -168,7 +205,9 @@ class AuthApiTest( body("code", equalTo(AdminErrorCode.ADMIN_NOT_FOUND.errorCode)) } ).also { - loginHistoryRepository.findAll() shouldHaveSize 0 + verify(exactly = 0) { + loginHistoryEventListener.onLoginCompleted(any()) + } } } } @@ -198,10 +237,13 @@ class AuthApiTest( ).also { extraAssertions?.invoke(it) - assertSoftly(loginHistoryRepository.findByPrincipalId(id)) { history -> - history shouldHaveSize (1) - history[0].success shouldBe true - history[0].principalType shouldBe type + verify(exactly = 1) { + loginHistoryEventListener.onLoginCompleted(any()) + } + assertSoftly(slot.captured) { + this.id shouldBe id + this.type shouldBe type + this.success shouldBe true } } } diff --git a/service/src/test/kotlin/com/sangdol/roomescape/auth/FailOnSaveLoginHistoryTest.kt b/service/src/test/kotlin/com/sangdol/roomescape/auth/FailOnSaveLoginHistoryTest.kt deleted file mode 100644 index 1a766de2..00000000 --- a/service/src/test/kotlin/com/sangdol/roomescape/auth/FailOnSaveLoginHistoryTest.kt +++ /dev/null @@ -1,64 +0,0 @@ -package com.sangdol.roomescape.auth - -import com.ninjasquad.springmockk.MockkBean -import com.sangdol.common.types.web.HttpStatus -import com.sangdol.roomescape.auth.infrastructure.persistence.LoginHistoryRepository -import com.sangdol.roomescape.auth.dto.LoginRequest -import com.sangdol.roomescape.auth.business.domain.PrincipalType -import com.sangdol.roomescape.supports.AdminFixture -import com.sangdol.roomescape.supports.FunSpecSpringbootTest -import com.sangdol.roomescape.supports.UserFixture -import com.sangdol.roomescape.supports.runTest -import io.mockk.clearMocks -import io.mockk.every - -class FailOnSaveLoginHistoryTest( - @MockkBean private val loginHistoryRepository: LoginHistoryRepository -) : FunSpecSpringbootTest() { - - init { - context("로그인 이력 저장 과정에서 예외가 발생해도 로그인 작업 자체는 정상 처리된다.") { - beforeTest { - clearMocks(loginHistoryRepository) - - every { - loginHistoryRepository.save(any()) - } throws RuntimeException("intended exception") - } - - test("회원") { - val user = testAuthUtil.signup(UserFixture.createRequest) - val request = LoginRequest(user.email, user.password, PrincipalType.USER) - - runTest( - using = { - body(request) - }, - on = { - post("/auth/login") - }, - expect = { - statusCode(HttpStatus.OK.value()) - } - ) - } - - test("관리자") { - val admin = testAuthUtil.createAdmin(AdminFixture.default) - val request = LoginRequest(admin.account, admin.password, PrincipalType.ADMIN) - - runTest( - using = { - body(request) - }, - on = { - post("/auth/login") - }, - expect = { - statusCode(HttpStatus.OK.value()) - } - ) - } - } - } -}