package roomescape.member.controller import io.kotest.assertions.assertSoftly import io.kotest.matchers.collections.shouldContainAll import io.kotest.matchers.shouldBe import io.mockk.every import io.mockk.mockk import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest import org.springframework.test.web.servlet.MockMvc import roomescape.auth.exception.AuthErrorCode import roomescape.member.exception.MemberErrorCode import roomescape.member.infrastructure.persistence.Role import roomescape.member.web.MemberController import roomescape.member.web.MemberRetrieveListResponse import roomescape.member.web.SignupRequest import roomescape.util.MemberFixture import roomescape.util.RoomescapeApiTest import kotlin.random.Random @WebMvcTest(controllers = [MemberController::class]) class MemberControllerTest( @Autowired private val mockMvc: MockMvc ) : RoomescapeApiTest() { init { given("GET /members 요청을") { val endpoint = "/members" every { memberRepository.findAll() } returns listOf( MemberFixture.create(id = Random.nextLong(), name = "name1"), MemberFixture.create(id = Random.nextLong(), name = "name2"), MemberFixture.create(id = Random.nextLong(), name = "name3"), ) `when`("관리자가 보내면") { loginAsAdmin() then("성공한다.") { val result: String = runGetTest( mockMvc = mockMvc, endpoint = endpoint, ) { status { isOk() } }.andReturn().response.contentAsString val response: MemberRetrieveListResponse = readValue( responseJson = result, valueType = MemberRetrieveListResponse::class.java ) assertSoftly(response.members) { it.size shouldBe 3 it.map { m -> m.name } shouldContainAll listOf("name1", "name2", "name3") } } } `when`("관리자가 아니면 에러 응답을 받는다.") { then("비회원") { doNotLogin() val expectedError = AuthErrorCode.INVALID_TOKEN runGetTest( mockMvc = mockMvc, endpoint = endpoint, ) { status { isEqualTo(expectedError.httpStatus.value()) } }.andExpect { jsonPath("$.code") { value(expectedError.errorCode) } } } then("일반 회원") { loginAsUser() val expectedError = AuthErrorCode.ACCESS_DENIED runGetTest( mockMvc = mockMvc, endpoint = endpoint, ) { status { isEqualTo(expectedError.httpStatus.value()) } }.andExpect { jsonPath("$.code") { value(expectedError.errorCode) } } } } } given("POST /members") { val endpoint = "/members" val request = SignupRequest( name = "name", email = "email@email.com", password = "password" ) `when`("같은 이메일이 없으면") { every { memberRepository.findByEmail(request.email) } returns null every { memberRepository.save(any()) } returns MemberFixture.create( id = 1, name = request.name, account = request.email, password = request.password, role = Role.MEMBER ) then("id과 이름을 담아 성공 응답") { runPostTest( mockMvc = mockMvc, endpoint = endpoint, body = request ) { status { isCreated() } jsonPath("$.data.name") { value(request.name) } jsonPath("$.data.id") { value(1) } } } } `when`("같은 이메일이 있으면") { every { memberRepository.findByEmail(request.email) } returns mockk() then("에러 응답") { val expectedError = MemberErrorCode.DUPLICATE_EMAIL runPostTest( mockMvc = mockMvc, endpoint = endpoint, body = request ) { status { isEqualTo(expectedError.httpStatus.value()) } jsonPath("$.code") { value(expectedError.errorCode) } } } } } } }