generated from pricelees/issue-pr-template
[#34] 회원 / 인증 도메인 재정의 #43
229
src/test/kotlin/roomescape/auth/AuthApiTest.kt
Normal file
229
src/test/kotlin/roomescape/auth/AuthApiTest.kt
Normal file
@ -0,0 +1,229 @@
|
||||
package roomescape.auth
|
||||
|
||||
import com.ninjasquad.springmockk.SpykBean
|
||||
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.restassured.response.ValidatableResponse
|
||||
import org.hamcrest.CoreMatchers.equalTo
|
||||
import org.springframework.http.HttpStatus
|
||||
import roomescape.admin.exception.AdminErrorCode
|
||||
import roomescape.auth.business.CLAIM_PERMISSION_KEY
|
||||
import roomescape.auth.exception.AuthErrorCode
|
||||
import roomescape.auth.infrastructure.jwt.JwtUtils
|
||||
import roomescape.auth.infrastructure.persistence.LoginHistoryRepository
|
||||
import roomescape.auth.web.LoginRequestV2
|
||||
import roomescape.common.dto.PrincipalType
|
||||
import roomescape.member.exception.UserErrorCode
|
||||
import roomescape.member.infrastructure.persistence.UserEntity
|
||||
import roomescape.util.AdminFixture
|
||||
import roomescape.util.FunSpecSpringbootTest
|
||||
import roomescape.util.UserFixture
|
||||
import roomescape.util.runTest
|
||||
|
||||
class AuthApiTest(
|
||||
@SpykBean private val jwtUtils: JwtUtils,
|
||||
private val loginHistoryRepository: LoginHistoryRepository
|
||||
) : FunSpecSpringbootTest() {
|
||||
|
||||
init {
|
||||
context("로그인을 시도한다.") {
|
||||
context("성공 응답") {
|
||||
test("관리자") {
|
||||
val admin = authUtil.createAdmin(AdminFixture.default)
|
||||
runLoginSuccessTest(
|
||||
id = admin.id,
|
||||
account = admin.account,
|
||||
password = admin.password,
|
||||
type = PrincipalType.ADMIN,
|
||||
) {
|
||||
val token: String = it.extract().path("data.accessToken")
|
||||
jwtUtils.extractSubject(token) shouldBe admin.id.toString()
|
||||
jwtUtils.extractClaim(token, CLAIM_PERMISSION_KEY) shouldBe admin.permissionLevel.name
|
||||
}
|
||||
}
|
||||
|
||||
test("회원") {
|
||||
val user: UserEntity = authUtil.signup(UserFixture.createRequest)
|
||||
|
||||
runLoginSuccessTest(
|
||||
id = user.id,
|
||||
account = user.email,
|
||||
password = user.password,
|
||||
type = PrincipalType.USER,
|
||||
) {
|
||||
val token: String = it.extract().path("data.accessToken")
|
||||
jwtUtils.extractSubject(token) shouldBe user.id.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context("실패 응답") {
|
||||
test("비밀번호가 틀린 경우") {
|
||||
val admin = authUtil.createAdmin(AdminFixture.default)
|
||||
val request = LoginRequestV2(admin.account, "wrong_password", PrincipalType.ADMIN)
|
||||
|
||||
runTest(
|
||||
using = {
|
||||
body(request)
|
||||
},
|
||||
on = {
|
||||
post("/auth/login")
|
||||
},
|
||||
expect = {
|
||||
statusCode(HttpStatus.UNAUTHORIZED.value())
|
||||
body("code", equalTo(AuthErrorCode.LOGIN_FAILED.errorCode))
|
||||
}
|
||||
).also {
|
||||
assertSoftly(loginHistoryRepository.findByPrincipalId(admin.id)[0]) {
|
||||
it.success shouldBe false
|
||||
it.principalType shouldBe PrincipalType.ADMIN
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test("토큰 생성 과정에서 오류가 발생하는 경우") {
|
||||
val admin = authUtil.createAdmin(AdminFixture.default)
|
||||
val request = LoginRequestV2(admin.account, admin.password, PrincipalType.ADMIN)
|
||||
|
||||
every {
|
||||
jwtUtils.createToken(any(), any())
|
||||
} throws RuntimeException("토큰 생성 실패")
|
||||
|
||||
runTest(
|
||||
using = {
|
||||
body(request)
|
||||
},
|
||||
on = {
|
||||
post("/auth/login")
|
||||
},
|
||||
expect = {
|
||||
statusCode(HttpStatus.INTERNAL_SERVER_ERROR.value())
|
||||
body("code", equalTo(AuthErrorCode.TEMPORARY_AUTH_ERROR.errorCode))
|
||||
}
|
||||
).also {
|
||||
assertSoftly(loginHistoryRepository.findByPrincipalId(admin.id)[0]) {
|
||||
it.success shouldBe false
|
||||
it.principalType shouldBe PrincipalType.ADMIN
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context("계정이 일치하지 않으면 로그인 실패 이력을 남기지 않는다.") {
|
||||
test("회원") {
|
||||
val user = authUtil.signup(UserFixture.createRequest)
|
||||
val invalidEmail = "test@email.com".also {
|
||||
it shouldNotBe user.email
|
||||
}
|
||||
|
||||
val request = LoginRequestV2(invalidEmail, user.password, PrincipalType.USER)
|
||||
|
||||
runTest(
|
||||
using = {
|
||||
body(request)
|
||||
},
|
||||
on = {
|
||||
post("/auth/login")
|
||||
},
|
||||
expect = {
|
||||
statusCode(HttpStatus.NOT_FOUND.value())
|
||||
body("code", equalTo(UserErrorCode.USER_NOT_FOUND.errorCode))
|
||||
}
|
||||
).also {
|
||||
loginHistoryRepository.findAll() shouldHaveSize 0
|
||||
}
|
||||
}
|
||||
|
||||
test("관리자") {
|
||||
val admin = authUtil.createAdmin(AdminFixture.default)
|
||||
val invalidAccount = "invalid".also {
|
||||
it shouldNotBe admin.account
|
||||
}
|
||||
|
||||
val request = LoginRequestV2(invalidAccount, admin.password, PrincipalType.ADMIN)
|
||||
|
||||
runTest(
|
||||
using = {
|
||||
body(request)
|
||||
},
|
||||
on = {
|
||||
post("/auth/login")
|
||||
},
|
||||
expect = {
|
||||
statusCode(HttpStatus.NOT_FOUND.value())
|
||||
body("code", equalTo(AdminErrorCode.ADMIN_NOT_FOUND.errorCode))
|
||||
}
|
||||
).also {
|
||||
loginHistoryRepository.findAll() shouldHaveSize 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context("로그인 상태를 확인한다.") {
|
||||
test("성공 응답") {
|
||||
val token = authUtil.defaultUserLogin()
|
||||
|
||||
runTest(
|
||||
token = token,
|
||||
on = {
|
||||
get("/auth/login/check")
|
||||
},
|
||||
expect = {
|
||||
statusCode(HttpStatus.OK.value())
|
||||
}
|
||||
).also {
|
||||
val name: String = it.extract().path("data.name")
|
||||
val type: String = it.extract().path("data.type")
|
||||
|
||||
name.isBlank() shouldBe false
|
||||
type shouldBe PrincipalType.USER.name
|
||||
}
|
||||
}
|
||||
|
||||
test("로그인 상태가 아니면 실패한다.") {
|
||||
runTest(
|
||||
on = {
|
||||
get("/auth/login/check")
|
||||
},
|
||||
expect = {
|
||||
statusCode(HttpStatus.UNAUTHORIZED.value())
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun runLoginSuccessTest(
|
||||
id: Long,
|
||||
account: String,
|
||||
password: String,
|
||||
type: PrincipalType,
|
||||
extraAssertions: ((ValidatableResponse) -> Unit)? = null
|
||||
) {
|
||||
val request = LoginRequestV2(account, password, type)
|
||||
|
||||
runTest(
|
||||
using = {
|
||||
body(request)
|
||||
},
|
||||
on = {
|
||||
post("/auth/login")
|
||||
},
|
||||
expect = {
|
||||
statusCode(HttpStatus.OK.value())
|
||||
}
|
||||
).also {
|
||||
extraAssertions?.invoke(it)
|
||||
|
||||
assertSoftly(loginHistoryRepository.findByPrincipalId(id)) { history ->
|
||||
history shouldHaveSize (1)
|
||||
history[0].success shouldBe true
|
||||
history[0].principalType shouldBe type
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,64 @@
|
||||
package roomescape.auth
|
||||
|
||||
import com.ninjasquad.springmockk.MockkBean
|
||||
import io.mockk.clearMocks
|
||||
import io.mockk.every
|
||||
import org.springframework.http.HttpStatus
|
||||
import roomescape.auth.infrastructure.persistence.LoginHistoryRepository
|
||||
import roomescape.auth.web.LoginRequestV2
|
||||
import roomescape.common.dto.PrincipalType
|
||||
import roomescape.util.AdminFixture
|
||||
import roomescape.util.FunSpecSpringbootTest
|
||||
import roomescape.util.UserFixture
|
||||
import roomescape.util.runTest
|
||||
|
||||
class FailOnSaveLoginHistoryTest(
|
||||
@MockkBean private val loginHistoryRepository: LoginHistoryRepository
|
||||
) : FunSpecSpringbootTest() {
|
||||
|
||||
init {
|
||||
context("로그인 이력 저장 과정에서 예외가 발생해도 로그인 작업 자체는 정상 처리된다.") {
|
||||
beforeTest {
|
||||
clearMocks(loginHistoryRepository)
|
||||
|
||||
every {
|
||||
loginHistoryRepository.save(any())
|
||||
} throws RuntimeException("intended exception")
|
||||
}
|
||||
|
||||
test("회원") {
|
||||
val user = authUtil.signup(UserFixture.createRequest)
|
||||
val request = LoginRequestV2(user.email, user.password, PrincipalType.USER)
|
||||
|
||||
runTest(
|
||||
using = {
|
||||
body(request)
|
||||
},
|
||||
on = {
|
||||
post("/auth/login")
|
||||
},
|
||||
expect = {
|
||||
statusCode(HttpStatus.OK.value())
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
test("관리자") {
|
||||
val admin = authUtil.createAdmin(AdminFixture.default)
|
||||
val request = LoginRequestV2(admin.account, admin.password, PrincipalType.ADMIN)
|
||||
|
||||
runTest(
|
||||
using = {
|
||||
body(request)
|
||||
},
|
||||
on = {
|
||||
post("/auth/login")
|
||||
},
|
||||
expect = {
|
||||
statusCode(HttpStatus.OK.value())
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user