generated from pricelees/issue-pr-template
[#30] 코드 구조 개선 #31
@ -1,25 +1,24 @@
|
|||||||
package roomescape.auth.web
|
package roomescape.auth.web
|
||||||
|
|
||||||
import com.ninjasquad.springmockk.SpykBean
|
import com.ninjasquad.springmockk.MockkBean
|
||||||
|
import io.mockk.Runs
|
||||||
import io.mockk.every
|
import io.mockk.every
|
||||||
|
import io.mockk.just
|
||||||
import org.hamcrest.Matchers.equalTo
|
import org.hamcrest.Matchers.equalTo
|
||||||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
|
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
|
||||||
import org.springframework.test.web.servlet.MockMvc
|
import org.springframework.test.web.servlet.MockMvc
|
||||||
import roomescape.auth.business.AuthService
|
import roomescape.auth.business.AuthService
|
||||||
import roomescape.auth.exception.AuthErrorCode
|
import roomescape.auth.exception.AuthErrorCode
|
||||||
|
import roomescape.auth.exception.AuthException
|
||||||
import roomescape.common.exception.CommonErrorCode
|
import roomescape.common.exception.CommonErrorCode
|
||||||
import roomescape.common.exception.ErrorCode
|
import roomescape.common.exception.ErrorCode
|
||||||
import roomescape.member.exception.MemberErrorCode
|
|
||||||
import roomescape.member.exception.MemberException
|
|
||||||
import roomescape.util.MemberFixture
|
import roomescape.util.MemberFixture
|
||||||
import roomescape.util.RoomescapeApiTest
|
import roomescape.util.RoomescapeApiTest
|
||||||
|
|
||||||
@WebMvcTest(controllers = [AuthController::class])
|
@WebMvcTest(controllers = [AuthController::class])
|
||||||
class AuthControllerTest(
|
class AuthControllerTest(val mockMvc: MockMvc) : RoomescapeApiTest() {
|
||||||
val mockMvc: MockMvc
|
|
||||||
) : RoomescapeApiTest() {
|
|
||||||
|
|
||||||
@SpykBean
|
@MockkBean
|
||||||
private lateinit var authService: AuthService
|
private lateinit var authService: AuthService
|
||||||
|
|
||||||
val userRequest: LoginRequest = MemberFixture.userLoginRequest()
|
val userRequest: LoginRequest = MemberFixture.userLoginRequest()
|
||||||
@ -32,12 +31,8 @@ class AuthControllerTest(
|
|||||||
val expectedToken = "expectedToken"
|
val expectedToken = "expectedToken"
|
||||||
|
|
||||||
every {
|
every {
|
||||||
memberFinder.findByEmailAndPassword(userRequest.email, userRequest.password)
|
authService.login(userRequest)
|
||||||
} returns user
|
} returns LoginResponse(expectedToken)
|
||||||
|
|
||||||
every {
|
|
||||||
jwtHandler.createToken(user.id!!)
|
|
||||||
} returns expectedToken
|
|
||||||
|
|
||||||
Then("토큰을 반환한다.") {
|
Then("토큰을 반환한다.") {
|
||||||
runPostTest(
|
runPostTest(
|
||||||
@ -52,12 +47,13 @@ class AuthControllerTest(
|
|||||||
}
|
}
|
||||||
|
|
||||||
When("회원을 찾지 못하면") {
|
When("회원을 찾지 못하면") {
|
||||||
|
val expectedError = AuthErrorCode.LOGIN_FAILED
|
||||||
|
|
||||||
every {
|
every {
|
||||||
memberFinder.findByEmailAndPassword(userRequest.email, userRequest.password)
|
authService.login(userRequest)
|
||||||
} throws MemberException(MemberErrorCode.MEMBER_NOT_FOUND)
|
} throws AuthException(expectedError)
|
||||||
|
|
||||||
Then("에러 응답을 받는다.") {
|
Then("에러 응답을 받는다.") {
|
||||||
val expectedError = AuthErrorCode.LOGIN_FAILED
|
|
||||||
runPostTest(
|
runPostTest(
|
||||||
mockMvc = mockMvc,
|
mockMvc = mockMvc,
|
||||||
endpoint = endpoint,
|
endpoint = endpoint,
|
||||||
@ -68,6 +64,7 @@ class AuthControllerTest(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
When("입력 값이 잘못되면") {
|
When("입력 값이 잘못되면") {
|
||||||
val expectedErrorCode: ErrorCode = CommonErrorCode.INVALID_INPUT_VALUE
|
val expectedErrorCode: ErrorCode = CommonErrorCode.INVALID_INPUT_VALUE
|
||||||
|
|
||||||
@ -97,6 +94,10 @@ class AuthControllerTest(
|
|||||||
loginAsUser()
|
loginAsUser()
|
||||||
|
|
||||||
Then("회원의 이름과 권한을 응답한다") {
|
Then("회원의 이름과 권한을 응답한다") {
|
||||||
|
every {
|
||||||
|
authService.checkLogin(user.id!!)
|
||||||
|
} returns LoginCheckResponse(user.name, user.role.name)
|
||||||
|
|
||||||
runGetTest(
|
runGetTest(
|
||||||
mockMvc = mockMvc,
|
mockMvc = mockMvc,
|
||||||
endpoint = endpoint,
|
endpoint = endpoint,
|
||||||
@ -110,14 +111,12 @@ class AuthControllerTest(
|
|||||||
|
|
||||||
When("토큰은 있지만 회원을 찾을 수 없으면") {
|
When("토큰은 있지만 회원을 찾을 수 없으면") {
|
||||||
val invalidMemberId: Long = -1L
|
val invalidMemberId: Long = -1L
|
||||||
|
val expectedError = AuthErrorCode.MEMBER_NOT_FOUND
|
||||||
|
|
||||||
every { jwtHandler.getMemberIdFromToken(any()) } returns invalidMemberId
|
every { jwtHandler.getMemberIdFromToken(any()) } returns invalidMemberId
|
||||||
every {
|
every { authService.checkLogin(invalidMemberId) } throws AuthException(expectedError)
|
||||||
memberFinder.findById(invalidMemberId)
|
|
||||||
} throws MemberException(MemberErrorCode.MEMBER_NOT_FOUND)
|
|
||||||
|
|
||||||
Then("에러 응답을 받는다.") {
|
Then("에러 응답을 받는다.") {
|
||||||
val expectedError = AuthErrorCode.MEMBER_NOT_FOUND
|
|
||||||
runGetTest(
|
runGetTest(
|
||||||
mockMvc = mockMvc,
|
mockMvc = mockMvc,
|
||||||
endpoint = endpoint,
|
endpoint = endpoint,
|
||||||
@ -132,13 +131,11 @@ class AuthControllerTest(
|
|||||||
val endpoint = "/logout"
|
val endpoint = "/logout"
|
||||||
|
|
||||||
When("토큰으로 memberId 조회가 가능하면") {
|
When("토큰으로 memberId 조회가 가능하면") {
|
||||||
every {
|
loginAsUser()
|
||||||
jwtHandler.getMemberIdFromToken(any())
|
|
||||||
} returns 1L
|
|
||||||
|
|
||||||
every {
|
every {
|
||||||
memberFinder.findById(1L)
|
authService.logout(user.id!!)
|
||||||
} returns MemberFixture.create(id = 1L)
|
} just Runs
|
||||||
|
|
||||||
Then("정상 응답한다.") {
|
Then("정상 응답한다.") {
|
||||||
runPostTest(
|
runPostTest(
|
||||||
|
|||||||
@ -1,68 +1,53 @@
|
|||||||
package roomescape.member.controller
|
package roomescape.member.controller
|
||||||
|
|
||||||
import com.ninjasquad.springmockk.MockkBean
|
import com.ninjasquad.springmockk.MockkBean
|
||||||
import com.ninjasquad.springmockk.SpykBean
|
|
||||||
import io.kotest.assertions.assertSoftly
|
import io.kotest.assertions.assertSoftly
|
||||||
import io.kotest.matchers.collections.shouldContainAll
|
import io.kotest.matchers.collections.shouldContainAll
|
||||||
import io.kotest.matchers.shouldBe
|
import io.kotest.matchers.shouldBe
|
||||||
import io.mockk.every
|
import io.mockk.every
|
||||||
import org.springframework.beans.factory.annotation.Autowired
|
|
||||||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
|
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
|
||||||
import org.springframework.test.web.servlet.MockMvc
|
import org.springframework.test.web.servlet.MockMvc
|
||||||
import roomescape.auth.exception.AuthErrorCode
|
import roomescape.auth.exception.AuthErrorCode
|
||||||
import roomescape.member.business.MemberService
|
import roomescape.member.business.MemberService
|
||||||
import roomescape.member.exception.MemberErrorCode
|
import roomescape.member.exception.MemberErrorCode
|
||||||
import roomescape.member.exception.MemberException
|
import roomescape.member.exception.MemberException
|
||||||
import roomescape.member.implement.MemberWriter
|
|
||||||
import roomescape.member.infrastructure.persistence.Role
|
import roomescape.member.infrastructure.persistence.Role
|
||||||
import roomescape.member.web.MemberController
|
import roomescape.member.web.*
|
||||||
import roomescape.member.web.MemberRetrieveListResponse
|
|
||||||
import roomescape.member.web.SignupRequest
|
|
||||||
import roomescape.util.MemberFixture
|
import roomescape.util.MemberFixture
|
||||||
import roomescape.util.RoomescapeApiTest
|
import roomescape.util.RoomescapeApiTest
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
@WebMvcTest(controllers = [MemberController::class])
|
@WebMvcTest(controllers = [MemberController::class])
|
||||||
class MemberControllerTest(
|
class MemberControllerTest(val mockMvc: MockMvc) : RoomescapeApiTest() {
|
||||||
@Autowired private val mockMvc: MockMvc
|
|
||||||
) : RoomescapeApiTest() {
|
|
||||||
|
|
||||||
@SpykBean
|
|
||||||
private lateinit var memberService: MemberService
|
|
||||||
|
|
||||||
@MockkBean
|
@MockkBean
|
||||||
private lateinit var memberWriter: MemberWriter
|
private lateinit var memberService: MemberService
|
||||||
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
given("GET /members 요청을") {
|
given("GET /members 요청을") {
|
||||||
val endpoint = "/members"
|
val endpoint = "/members"
|
||||||
|
val response = listOf(
|
||||||
every { memberFinder.findAll() } returns listOf(
|
|
||||||
MemberFixture.create(id = Random.nextLong(), name = "name1"),
|
MemberFixture.create(id = Random.nextLong(), name = "name1"),
|
||||||
MemberFixture.create(id = Random.nextLong(), name = "name2"),
|
MemberFixture.create(id = Random.nextLong(), name = "name2"),
|
||||||
MemberFixture.create(id = Random.nextLong(), name = "name3"),
|
MemberFixture.create(id = Random.nextLong(), name = "name3"),
|
||||||
)
|
).toRetrieveListResponse()
|
||||||
|
|
||||||
|
every { memberService.findMembers() } returns response
|
||||||
|
|
||||||
`when`("관리자가 보내면") {
|
`when`("관리자가 보내면") {
|
||||||
loginAsAdmin()
|
loginAsAdmin()
|
||||||
|
|
||||||
then("성공한다.") {
|
then("성공한다.") {
|
||||||
val result: String = runGetTest(
|
val result: MemberRetrieveListResponse = runGetTest(
|
||||||
mockMvc = mockMvc,
|
mockMvc = mockMvc,
|
||||||
endpoint = endpoint,
|
endpoint = endpoint,
|
||||||
) {
|
) {
|
||||||
status { isOk() }
|
status { isOk() }
|
||||||
}.andReturn().response.contentAsString
|
}.andReturn().readValue(MemberRetrieveListResponse::class.java)
|
||||||
|
|
||||||
val response: MemberRetrieveListResponse = readValue(
|
|
||||||
responseJson = result,
|
|
||||||
valueType = MemberRetrieveListResponse::class.java
|
|
||||||
)
|
|
||||||
|
|
||||||
assertSoftly(response.members) {
|
assertSoftly(result.members) {
|
||||||
it.size shouldBe 3
|
it.size shouldBe response.members.size
|
||||||
it.map { m -> m.name } shouldContainAll listOf("name1", "name2", "name3")
|
it.map { m -> m.name } shouldContainAll response.members.map { m -> m.name }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -107,14 +92,14 @@ class MemberControllerTest(
|
|||||||
)
|
)
|
||||||
`when`("같은 이메일이 없으면") {
|
`when`("같은 이메일이 없으면") {
|
||||||
every {
|
every {
|
||||||
memberWriter.create(any(), any(), any(), any())
|
memberService.createMember(request)
|
||||||
} returns MemberFixture.create(
|
} returns MemberFixture.create(
|
||||||
id = 1,
|
id = 1,
|
||||||
name = request.name,
|
name = request.name,
|
||||||
account = request.email,
|
account = request.email,
|
||||||
password = request.password,
|
password = request.password,
|
||||||
role = Role.MEMBER
|
role = Role.MEMBER
|
||||||
)
|
).toSignupResponse()
|
||||||
|
|
||||||
then("id과 이름을 담아 성공 응답") {
|
then("id과 이름을 담아 성공 응답") {
|
||||||
runPostTest(
|
runPostTest(
|
||||||
@ -130,13 +115,12 @@ class MemberControllerTest(
|
|||||||
}
|
}
|
||||||
|
|
||||||
`when`("같은 이메일이 있으면") {
|
`when`("같은 이메일이 있으면") {
|
||||||
|
val expectedError = MemberErrorCode.DUPLICATE_EMAIL
|
||||||
every {
|
every {
|
||||||
memberWriter.create(request.name, request.email, request.password, Role.MEMBER)
|
memberService.createMember(request)
|
||||||
} throws MemberException(MemberErrorCode.DUPLICATE_EMAIL)
|
} throws MemberException(expectedError)
|
||||||
|
|
||||||
then("에러 응답") {
|
then("에러 응답") {
|
||||||
val expectedError = MemberErrorCode.DUPLICATE_EMAIL
|
|
||||||
|
|
||||||
runPostTest(
|
runPostTest(
|
||||||
mockMvc = mockMvc,
|
mockMvc = mockMvc,
|
||||||
endpoint = endpoint,
|
endpoint = endpoint,
|
||||||
|
|||||||
@ -21,18 +21,15 @@ import java.time.LocalDate
|
|||||||
import java.time.LocalTime
|
import java.time.LocalTime
|
||||||
|
|
||||||
@WebMvcTest(TimeController::class)
|
@WebMvcTest(TimeController::class)
|
||||||
class TimeControllerTest(
|
class TimeControllerTest(val mockMvc: MockMvc) : RoomescapeApiTest() {
|
||||||
val mockMvc: MockMvc,
|
|
||||||
) : RoomescapeApiTest() {
|
|
||||||
|
|
||||||
@MockkBean
|
@MockkBean
|
||||||
private lateinit var timeService: TimeService
|
private lateinit var timeService: TimeService
|
||||||
|
|
||||||
init {
|
init {
|
||||||
Given("등록된 모든 시간을 조회할 때") {
|
Given("GET /times 요청을") {
|
||||||
val endpoint = "/times"
|
val endpoint = "/times"
|
||||||
|
|
||||||
When("관리자인 경우") {
|
When("관리자가 보내면") {
|
||||||
beforeTest {
|
beforeTest {
|
||||||
loginAsAdmin()
|
loginAsAdmin()
|
||||||
}
|
}
|
||||||
@ -59,7 +56,7 @@ class TimeControllerTest(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
When("관리자가 아닌 경우") {
|
When("관리자가 보내지 않았다면") {
|
||||||
loginAsUser()
|
loginAsUser()
|
||||||
val expectedError = AuthErrorCode.ACCESS_DENIED
|
val expectedError = AuthErrorCode.ACCESS_DENIED
|
||||||
|
|
||||||
@ -79,10 +76,10 @@ class TimeControllerTest(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Given("시간을 추가할 때") {
|
Given("POST /times 요청을") {
|
||||||
val endpoint = "/times"
|
val endpoint = "/times"
|
||||||
|
|
||||||
When("관리자인 경우") {
|
When("관리자가 보낼 때") {
|
||||||
beforeTest {
|
beforeTest {
|
||||||
loginAsAdmin()
|
loginAsAdmin()
|
||||||
}
|
}
|
||||||
@ -143,7 +140,7 @@ class TimeControllerTest(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
When("관리자가 아닌 경우") {
|
When("관리자가 보내지 않았다면") {
|
||||||
loginAsUser()
|
loginAsUser()
|
||||||
|
|
||||||
Then("예외 응답") {
|
Then("예외 응답") {
|
||||||
@ -160,10 +157,10 @@ class TimeControllerTest(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Given("시간을 삭제할 때") {
|
Given("DELETE /times/{id} 요청을") {
|
||||||
val endpoint = "/times/1"
|
val endpoint = "/times/1"
|
||||||
|
|
||||||
When("관리자인 경우") {
|
When("관리자가 보낼 때") {
|
||||||
beforeTest {
|
beforeTest {
|
||||||
loginAsAdmin()
|
loginAsAdmin()
|
||||||
}
|
}
|
||||||
@ -222,7 +219,7 @@ class TimeControllerTest(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
When("관리자가 아닌 경우") {
|
When("관리자가 보내지 않았다면") {
|
||||||
loginAsUser()
|
loginAsUser()
|
||||||
|
|
||||||
Then("예외 응답") {
|
Then("예외 응답") {
|
||||||
@ -238,28 +235,21 @@ class TimeControllerTest(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Given("날짜, 테마가 주어졌을 때") {
|
Given("GET /times/search?date={date}&themeId={themeId} 요청을 ") {
|
||||||
beforeTest {
|
|
||||||
loginAsUser()
|
|
||||||
}
|
|
||||||
val date: LocalDate = LocalDate.now()
|
val date: LocalDate = LocalDate.now()
|
||||||
val themeId = 1L
|
val themeId = 1L
|
||||||
|
|
||||||
When("테마를 찾을 수 있으면") {
|
When("회원이 보낼 때") {
|
||||||
Then("해당 날짜와 테마에 대한 예약 여부가 담긴 모든 시간을 응답") {
|
beforeTest {
|
||||||
|
loginAsUser()
|
||||||
|
}
|
||||||
|
|
||||||
|
Then("정상 응답") {
|
||||||
val response = TimeWithAvailabilityListResponse(
|
val response = TimeWithAvailabilityListResponse(
|
||||||
listOf(
|
listOf(
|
||||||
TimeWithAvailabilityResponse(id = 1L, startAt = LocalTime.now(), isAvailable = true),
|
TimeWithAvailabilityResponse(1L, LocalTime.of(10, 0), true),
|
||||||
TimeWithAvailabilityResponse(
|
TimeWithAvailabilityResponse(2L, LocalTime.of(10, 1), false),
|
||||||
id = 2L,
|
TimeWithAvailabilityResponse(3L, LocalTime.of(10, 2), true)
|
||||||
startAt = LocalTime.now().plusMinutes(30),
|
|
||||||
isAvailable = false
|
|
||||||
),
|
|
||||||
TimeWithAvailabilityResponse(
|
|
||||||
id = 1L,
|
|
||||||
startAt = LocalTime.now().plusHours(1),
|
|
||||||
isAvailable = true
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
every {
|
every {
|
||||||
@ -285,15 +275,12 @@ class TimeControllerTest(
|
|||||||
this[1].isAvailable shouldBe response.times[1].isAvailable
|
this[1].isAvailable shouldBe response.times[1].isAvailable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
Then("테마를 찾을 수 없으면 예외 응답") {
|
||||||
|
val expectedError = ThemeErrorCode.THEME_NOT_FOUND
|
||||||
|
every {
|
||||||
|
timeService.findTimesWithAvailability(date, themeId)
|
||||||
|
} throws ThemeException(expectedError)
|
||||||
|
|
||||||
When("테마를 찾을 수 없으면") {
|
|
||||||
val expectedError = ThemeErrorCode.THEME_NOT_FOUND
|
|
||||||
every {
|
|
||||||
timeService.findTimesWithAvailability(date, themeId)
|
|
||||||
} throws ThemeException(expectedError)
|
|
||||||
|
|
||||||
Then("예외 응답") {
|
|
||||||
runGetTest(
|
runGetTest(
|
||||||
mockMvc = mockMvc,
|
mockMvc = mockMvc,
|
||||||
endpoint = "/times/search?date=$date&themeId=$themeId",
|
endpoint = "/times/search?date=$date&themeId=$themeId",
|
||||||
@ -303,6 +290,23 @@ class TimeControllerTest(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
When("비회원이 보내면") {
|
||||||
|
doNotLogin()
|
||||||
|
|
||||||
|
Then("예외 응답") {
|
||||||
|
val expectedError = AuthErrorCode.MEMBER_NOT_FOUND
|
||||||
|
|
||||||
|
runGetTest(
|
||||||
|
mockMvc = mockMvc,
|
||||||
|
endpoint = "/times/search?date=$date&themeId=$themeId",
|
||||||
|
) {
|
||||||
|
status { isEqualTo(expectedError.httpStatus.value()) }
|
||||||
|
jsonPath("$.code", equalTo(expectedError.errorCode))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user