diff --git a/src/test/kotlin/roomescape/auth/business/AuthServiceTest.kt b/src/test/kotlin/roomescape/auth/business/AuthServiceTest.kt deleted file mode 100644 index 8609ba3e..00000000 --- a/src/test/kotlin/roomescape/auth/business/AuthServiceTest.kt +++ /dev/null @@ -1,82 +0,0 @@ -package roomescape.auth.business - -import io.kotest.assertions.assertSoftly -import io.kotest.assertions.throwables.shouldThrow -import io.kotest.core.spec.style.BehaviorSpec -import io.kotest.matchers.shouldBe -import io.mockk.every -import io.mockk.mockk -import roomescape.auth.exception.AuthErrorCode -import roomescape.auth.exception.AuthException -import roomescape.auth.infrastructure.jwt.JwtHandler -import roomescape.member.exception.MemberErrorCode -import roomescape.member.exception.MemberException -import roomescape.member.implement.MemberFinder -import roomescape.member.infrastructure.persistence.MemberEntity -import roomescape.util.JwtFixture -import roomescape.util.MemberFixture - -class AuthServiceTest : BehaviorSpec({ - val memberFinder: MemberFinder = mockk() - val jwtHandler: JwtHandler = JwtFixture.create() - - val authService = AuthService(memberFinder, jwtHandler) - val user: MemberEntity = MemberFixture.user() - - Given("로그인 요청을 받으면") { - When("이메일과 비밀번호로 회원을 찾고") { - val request = MemberFixture.userLoginRequest() - - Then("회원이 있다면 JWT 토큰을 생성한 뒤 반환한다.") { - every { - memberFinder.findByEmailAndPassword(request.email, request.password) - } returns user - - val accessToken: String = authService.login(request).accessToken - - accessToken.isNotBlank() shouldBe true - jwtHandler.getMemberIdFromToken(accessToken) shouldBe user.id - } - - Then("회원이 없다면 예외를 던진다.") { - every { - memberFinder.findByEmailAndPassword(request.email, request.password) - } throws MemberException(MemberErrorCode.MEMBER_NOT_FOUND) - - val exception = shouldThrow { - authService.login(request) - } - - exception.errorCode shouldBe AuthErrorCode.LOGIN_FAILED - } - } - } - - Given("로그인 확인 요청을 받으면") { - When("회원 ID로 회원을 찾고") { - val userId: Long = user.id!! - - Then("회원이 있다면 회원의 이름을 반환한다.") { - every { memberFinder.findById(userId) } returns user - - val response = authService.checkLogin(userId) - - assertSoftly(response) { - this.name shouldBe user.name - } - } - - Then("회원이 없다면 예외를 던진다.") { - every { - memberFinder.findById(userId) - } throws MemberException(MemberErrorCode.MEMBER_NOT_FOUND) - - val exception = shouldThrow { - authService.checkLogin(userId) - } - - exception.errorCode shouldBe AuthErrorCode.MEMBER_NOT_FOUND - } - } - } -}) diff --git a/src/test/kotlin/roomescape/auth/infrastructure/jwt/JwtHandlerTest.kt b/src/test/kotlin/roomescape/auth/infrastructure/jwt/JwtHandlerTest.kt deleted file mode 100644 index 9d9c91bc..00000000 --- a/src/test/kotlin/roomescape/auth/infrastructure/jwt/JwtHandlerTest.kt +++ /dev/null @@ -1,59 +0,0 @@ -package roomescape.auth.infrastructure.jwt - -import io.jsonwebtoken.Jwts -import io.jsonwebtoken.security.Keys -import io.kotest.assertions.throwables.shouldThrow -import io.kotest.core.spec.style.FunSpec -import io.kotest.matchers.shouldBe -import roomescape.auth.exception.AuthErrorCode -import roomescape.auth.exception.AuthException -import roomescape.util.JwtFixture -import java.util.* -import kotlin.random.Random - -class JwtHandlerTest : FunSpec({ - - context("JWT 토큰 조회") { - val memberId = Random.nextLong() - val jwtHandler: JwtHandler = JwtFixture.create() - - test("토큰에서 멤버 ID를 올바르게 추출한다.") { - val token = jwtHandler.createToken(memberId) - val extractedMemberId = jwtHandler.getMemberIdFromToken(token) - - extractedMemberId shouldBe memberId - } - - test("만료된 토큰이면 예외를 던진다.") { - val expirationTime = 0L - val shortExpirationTimeJwtHandler: JwtHandler = JwtFixture.create(expirationTime = expirationTime) - val token = shortExpirationTimeJwtHandler.createToken(memberId) - - Thread.sleep(expirationTime) // 만료 시간 이후로 대기 - - shouldThrow { - shortExpirationTimeJwtHandler.getMemberIdFromToken(token) - }.errorCode shouldBe AuthErrorCode.EXPIRED_TOKEN - } - - test("토큰이 빈 값이면 예외를 던진다.") { - shouldThrow { - jwtHandler.getMemberIdFromToken("") - }.errorCode shouldBe AuthErrorCode.TOKEN_NOT_FOUND - } - - test("시크릿 키가 잘못된 경우 예외를 던진다.") { - val now = Date() - val invalidSignatureToken: String = Jwts.builder() - .claim("memberId", memberId) - .issuedAt(now) - .expiration(Date(now.time + JwtFixture.EXPIRATION_TIME)) - .signWith(Keys.hmacShaKeyFor(JwtFixture.SECRET_KEY_STRING.substring(1).toByteArray())) - .compact() - - shouldThrow { - jwtHandler.getMemberIdFromToken(invalidSignatureToken) - }.errorCode shouldBe AuthErrorCode.INVALID_TOKEN - } - } -}) diff --git a/src/test/kotlin/roomescape/auth/web/AuthControllerTest.kt b/src/test/kotlin/roomescape/auth/web/AuthControllerTest.kt deleted file mode 100644 index aed2ee55..00000000 --- a/src/test/kotlin/roomescape/auth/web/AuthControllerTest.kt +++ /dev/null @@ -1,151 +0,0 @@ -package roomescape.auth.web - -import com.ninjasquad.springmockk.MockkBean -import io.mockk.Runs -import io.mockk.every -import io.mockk.just -import org.hamcrest.Matchers.equalTo -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest -import org.springframework.test.web.servlet.MockMvc -import roomescape.auth.business.AuthService -import roomescape.auth.exception.AuthErrorCode -import roomescape.auth.exception.AuthException -import roomescape.common.exception.CommonErrorCode -import roomescape.common.exception.ErrorCode -import roomescape.util.MemberFixture -import roomescape.util.RoomescapeApiTest - -@WebMvcTest(controllers = [AuthController::class]) -class AuthControllerTest(val mockMvc: MockMvc) : RoomescapeApiTest() { - - @MockkBean - private lateinit var authService: AuthService - - val userRequest: LoginRequest = MemberFixture.userLoginRequest() - - init { - Given("로그인 요청을 보낼 때") { - val endpoint = "/login" - - When("로그인에 성공하면") { - val expectedToken = "expectedToken" - - every { - authService.login(userRequest) - } returns LoginResponse(expectedToken) - - Then("토큰을 반환한다.") { - runPostTest( - mockMvc = mockMvc, - endpoint = endpoint, - body = userRequest, - ) { - status { isOk() } - jsonPath("$.data.accessToken", equalTo(expectedToken)) - } - } - } - - When("회원을 찾지 못하면") { - val expectedError = AuthErrorCode.LOGIN_FAILED - - every { - authService.login(userRequest) - } throws AuthException(expectedError) - - Then("에러 응답을 받는다.") { - runPostTest( - mockMvc = mockMvc, - endpoint = endpoint, - body = userRequest, - ) { - status { isEqualTo(expectedError.httpStatus.value()) } - jsonPath("$.code", equalTo(expectedError.errorCode)) - } - } - } - - When("입력 값이 잘못되면") { - val expectedErrorCode: ErrorCode = CommonErrorCode.INVALID_INPUT_VALUE - - Then("400 에러를 응답한다") { - listOf( - userRequest.copy(email = "invalid"), - userRequest.copy(password = " "), - "{\"email\": \"null\", \"password\": \"null\"}" - ).forEach { - runPostTest( - mockMvc = mockMvc, - endpoint = endpoint, - body = it, - ) { - status { isEqualTo(expectedErrorCode.httpStatus.value()) } - jsonPath("$.code", equalTo(expectedErrorCode.errorCode)) - } - } - } - } - } - - Given("로그인 상태를 확인할 때") { - val endpoint = "/login/check" - - When("로그인된 회원의 ID로 요청하면") { - loginAsUser() - - Then("회원의 이름과 권한을 응답한다") { - every { - authService.checkLogin(user.id!!) - } returns LoginCheckResponse(user.name, user.role.name) - - runGetTest( - mockMvc = mockMvc, - endpoint = endpoint, - ) { - status { isOk() } - jsonPath("$.data.name", equalTo(user.name)) - jsonPath("$.data.role", equalTo(user.role.name)) - } - } - } - - When("토큰은 있지만 회원을 찾을 수 없으면") { - val invalidMemberId: Long = -1L - val expectedError = AuthErrorCode.MEMBER_NOT_FOUND - - every { jwtHandler.getMemberIdFromToken(any()) } returns invalidMemberId - every { authService.checkLogin(invalidMemberId) } throws AuthException(expectedError) - - Then("에러 응답을 받는다.") { - runGetTest( - mockMvc = mockMvc, - endpoint = endpoint, - ) { - status { isEqualTo(expectedError.httpStatus.value()) } - jsonPath("$.code", equalTo(expectedError.errorCode)) - } - } - } - } - Given("로그아웃 요청을 보낼 때") { - val endpoint = "/logout" - - When("토큰으로 memberId 조회가 가능하면") { - loginAsUser() - - every { - authService.logout(user.id!!) - } just Runs - - Then("정상 응답한다.") { - runPostTest( - mockMvc = mockMvc, - endpoint = endpoint, - ) { - status { isNoContent() } - } - } - } - } - } -} diff --git a/src/test/kotlin/roomescape/auth/web/support/CookieUtilsTest.kt b/src/test/kotlin/roomescape/auth/web/support/CookieUtilsTest.kt deleted file mode 100644 index 2ec94157..00000000 --- a/src/test/kotlin/roomescape/auth/web/support/CookieUtilsTest.kt +++ /dev/null @@ -1,26 +0,0 @@ -package roomescape.auth.web.support - -import io.kotest.core.spec.style.FunSpec -import io.kotest.matchers.shouldBe -import io.mockk.every -import io.mockk.mockk -import jakarta.servlet.http.HttpServletRequest - -class CookieUtilsTest : FunSpec({ - context("accessToken 쿠키를 가져온다.") { - val httpServletRequest: HttpServletRequest = mockk() - - test("accessToken이 있으면 해당 쿠키를 반환한다.") { - val token = "test-token" - every { httpServletRequest.getHeader("Authorization") } returns "Bearer $token" - - httpServletRequest.accessToken() shouldBe token - } - - test("accessToken이 없으면 null을 반환한다.") { - every { httpServletRequest.getHeader("Authorization") } returns null - - httpServletRequest.accessToken() shouldBe null - } - } -}) diff --git a/src/test/kotlin/roomescape/member/business/MemberServiceTest.kt b/src/test/kotlin/roomescape/member/business/MemberServiceTest.kt deleted file mode 100644 index db82fc0b..00000000 --- a/src/test/kotlin/roomescape/member/business/MemberServiceTest.kt +++ /dev/null @@ -1,100 +0,0 @@ -package roomescape.member.business - -import io.kotest.assertions.assertSoftly -import io.kotest.assertions.throwables.shouldThrow -import io.kotest.core.spec.style.FunSpec -import io.kotest.matchers.collections.shouldContainExactly -import io.kotest.matchers.collections.shouldHaveSize -import io.kotest.matchers.shouldBe -import io.mockk.every -import io.mockk.mockk -import roomescape.member.exception.MemberErrorCode -import roomescape.member.exception.MemberException -import roomescape.member.implement.MemberFinder -import roomescape.member.implement.MemberWriter -import roomescape.member.infrastructure.persistence.MemberEntity -import roomescape.member.infrastructure.persistence.Role -import roomescape.member.web.SignupRequest -import roomescape.util.MemberFixture - -class MemberServiceTest : FunSpec({ - val memberWriter: MemberWriter = mockk() - val memberFinder: MemberFinder = mockk() - - val memberService = MemberService(memberWriter, memberFinder) - - context("findMembers") { - test("정상 응답") { - val members: List = listOf( - MemberFixture.create(name = "user1"), - MemberFixture.create(name = "user2"), - ) - - every { memberFinder.findAll() } returns members - - val response = memberService.findMembers() - - // then - assertSoftly(response.members) { - it shouldHaveSize 2 - it.map { member -> member.name } shouldContainExactly listOf("user1", "user2") - } - } - } - - context("findById") { - val id = 1L - - test("정상 응답") { - every { - memberFinder.findById(id) - } returns MemberFixture.create(id = id) - - memberService.findById(id).id shouldBe id - } - - test("회원을 찾을 수 없으면 예외 응답") { - every { - memberFinder.findById(id) - } throws MemberException(MemberErrorCode.MEMBER_NOT_FOUND) - - shouldThrow { - memberService.findById(id) - }.also { - it.errorCode shouldBe MemberErrorCode.MEMBER_NOT_FOUND - } - } - } - - context("createMember") { - val request = SignupRequest(name = "new-user", email = "new@test.com", password = "password") - - test("정상 저장") { - val member = MemberFixture.create( - name = request.name, - account = request.email, - password = request.password - ) - - every { - memberWriter.create(request.name, request.email, request.password, Role.MEMBER) - } returns member - - val response = memberService.createMember(request) - - response.id shouldBe member.id - } - - test("중복된 이메일이 있으면 예외 응답") { - every { - memberWriter.create(request.name, request.email, request.password, Role.MEMBER) - } throws MemberException(MemberErrorCode.DUPLICATE_EMAIL) - - shouldThrow { - memberService.createMember(request) - }.also { - it.errorCode shouldBe MemberErrorCode.DUPLICATE_EMAIL - } - } - } -}) diff --git a/src/test/kotlin/roomescape/member/controller/MemberControllerTest.kt b/src/test/kotlin/roomescape/member/controller/MemberControllerTest.kt deleted file mode 100644 index 5f3a9dc1..00000000 --- a/src/test/kotlin/roomescape/member/controller/MemberControllerTest.kt +++ /dev/null @@ -1,136 +0,0 @@ -package roomescape.member.controller - -import com.ninjasquad.springmockk.MockkBean -import io.kotest.assertions.assertSoftly -import io.kotest.matchers.collections.shouldContainAll -import io.kotest.matchers.shouldBe -import io.mockk.every -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest -import org.springframework.test.web.servlet.MockMvc -import roomescape.auth.exception.AuthErrorCode -import roomescape.member.business.MemberService -import roomescape.member.exception.MemberErrorCode -import roomescape.member.exception.MemberException -import roomescape.member.infrastructure.persistence.Role -import roomescape.member.web.* -import roomescape.util.MemberFixture -import roomescape.util.RoomescapeApiTest -import kotlin.random.Random - -@WebMvcTest(controllers = [MemberController::class]) -class MemberControllerTest(val mockMvc: MockMvc) : RoomescapeApiTest() { - @MockkBean - private lateinit var memberService: MemberService - - init { - given("GET /members 요청을") { - val endpoint = "/members" - val response = listOf( - MemberFixture.create(id = Random.nextLong(), name = "name1"), - MemberFixture.create(id = Random.nextLong(), name = "name2"), - MemberFixture.create(id = Random.nextLong(), name = "name3"), - ).toRetrieveListResponse() - - every { memberService.findMembers() } returns response - - `when`("관리자가 보내면") { - loginAsAdmin() - - then("성공한다.") { - val result: MemberRetrieveListResponse = runGetTest( - mockMvc = mockMvc, - endpoint = endpoint, - ) { - status { isOk() } - }.andReturn().readValue(MemberRetrieveListResponse::class.java) - - - assertSoftly(result.members) { - it.size shouldBe response.members.size - it.map { m -> m.name } shouldContainAll response.members.map { m -> m.name } - } - } - } - - `when`("관리자가 아니면 에러 응답을 받는다.") { - then("비회원") { - doNotLogin() - val expectedError = AuthErrorCode.MEMBER_NOT_FOUND - - 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 { - memberService.createMember(request) - } returns MemberFixture.create( - id = 1, - name = request.name, - account = request.email, - password = request.password, - role = Role.MEMBER - ).toSignupResponse() - - then("id과 이름을 담아 성공 응답") { - runPostTest( - mockMvc = mockMvc, - endpoint = endpoint, - body = request - ) { - status { isCreated() } - jsonPath("$.data.name") { value(request.name) } - jsonPath("$.data.id") { value(1) } - } - } - } - - `when`("같은 이메일이 있으면") { - val expectedError = MemberErrorCode.DUPLICATE_EMAIL - every { - memberService.createMember(request) - } throws MemberException(expectedError) - - then("에러 응답") { - runPostTest( - mockMvc = mockMvc, - endpoint = endpoint, - body = request - ) { - status { isEqualTo(expectedError.httpStatus.value()) } - jsonPath("$.code") { value(expectedError.errorCode) } - } - } - } - } - } -} diff --git a/src/test/kotlin/roomescape/member/implement/MemberFinderTest.kt b/src/test/kotlin/roomescape/member/implement/MemberFinderTest.kt deleted file mode 100644 index e1be29f7..00000000 --- a/src/test/kotlin/roomescape/member/implement/MemberFinderTest.kt +++ /dev/null @@ -1,85 +0,0 @@ -package roomescape.member.implement - -import io.kotest.assertions.throwables.shouldThrow -import io.kotest.core.spec.style.FunSpec -import io.kotest.matchers.collections.shouldHaveSize -import io.kotest.matchers.shouldBe -import io.mockk.every -import io.mockk.mockk -import io.mockk.verify -import org.springframework.data.repository.findByIdOrNull -import roomescape.member.exception.MemberErrorCode -import roomescape.member.exception.MemberException -import roomescape.member.infrastructure.persistence.MemberRepository - -class MemberFinderTest : FunSpec({ - - val memberRepository: MemberRepository = mockk() - val memberFinder = MemberFinder(memberRepository) - - context("findAll") { - test("모든 회원을 조회한다.") { - every { - memberRepository.findAll() - } returns listOf(mockk(), mockk(), mockk()) - - memberFinder.findAll() shouldHaveSize 3 - } - } - - context("findById") { - val memberId = 1L - test("동일한 ID인 회원을 찾아 응답한다.") { - every { - memberRepository.findByIdOrNull(memberId) - } returns mockk() - - memberFinder.findById(memberId) - - verify(exactly = 1) { - memberRepository.findByIdOrNull(memberId) - } - } - - test("동일한 ID인 회원이 없으면 실패한다.") { - every { - memberRepository.findByIdOrNull(memberId) - } returns null - - shouldThrow { - memberFinder.findById(memberId) - }.also { - it.errorCode shouldBe MemberErrorCode.MEMBER_NOT_FOUND - } - } - } - - context("findByEmailAndPassword") { - val email = "email" - val password = "password" - - test("동일한 이메일과 비밀번호를 가진 회원을 찾아 응답한다.") { - every { - memberRepository.findByEmailAndPassword(email, password) - } returns mockk() - - memberFinder.findByEmailAndPassword(email, password) - - verify(exactly = 1) { - memberRepository.findByEmailAndPassword(email, password) - } - } - - test("동일한 이메일과 비밀번호를 가진 회원이 없으면 실패한다.") { - every { - memberRepository.findByEmailAndPassword(email, password) - } returns null - - shouldThrow { - memberFinder.findByEmailAndPassword(email, password) - }.also { - it.errorCode shouldBe MemberErrorCode.MEMBER_NOT_FOUND - } - } - } -}) diff --git a/src/test/kotlin/roomescape/member/implement/MemberValidatorTest.kt b/src/test/kotlin/roomescape/member/implement/MemberValidatorTest.kt deleted file mode 100644 index ade55e4b..00000000 --- a/src/test/kotlin/roomescape/member/implement/MemberValidatorTest.kt +++ /dev/null @@ -1,44 +0,0 @@ -package roomescape.member.implement - -import io.kotest.assertions.throwables.shouldNotThrow -import io.kotest.assertions.throwables.shouldThrow -import io.kotest.core.spec.style.FunSpec -import io.kotest.core.spec.style.StringSpec -import io.kotest.matchers.shouldBe -import io.mockk.every -import io.mockk.mockk -import roomescape.member.exception.MemberErrorCode -import roomescape.member.exception.MemberException -import roomescape.member.infrastructure.persistence.MemberRepository - -class MemberValidatorTest : FunSpec({ - - val memberRepository: MemberRepository = mockk() - val memberValidator = MemberValidator(memberRepository) - - context("validateCanSignup") { - val email = "email@email.com" - - test("같은 이메일을 가진 회원이 있으면 예외를 던진다.") { - every { - memberRepository.existsByEmail(email) - } returns true - - shouldThrow { - memberValidator.validateCanSignup(email) - }.also { - it.errorCode shouldBe MemberErrorCode.DUPLICATE_EMAIL - } - } - - test("같은 이메일을 가진 회원이 없으면 종료한다.") { - every { - memberRepository.existsByEmail(email) - } returns false - - shouldNotThrow { - memberValidator.validateCanSignup(email) - } - } - } -}) diff --git a/src/test/kotlin/roomescape/member/implement/MemberWriterTest.kt b/src/test/kotlin/roomescape/member/implement/MemberWriterTest.kt deleted file mode 100644 index 16e09201..00000000 --- a/src/test/kotlin/roomescape/member/implement/MemberWriterTest.kt +++ /dev/null @@ -1,65 +0,0 @@ -package roomescape.member.implement - -import io.kotest.assertions.throwables.shouldThrow -import io.kotest.core.spec.style.FunSpec -import io.kotest.core.spec.style.StringSpec -import io.kotest.matchers.nulls.shouldNotBeNull -import io.kotest.matchers.shouldBe -import io.mockk.every -import io.mockk.mockk -import io.mockk.slot -import io.mockk.spyk -import io.mockk.verify -import roomescape.member.exception.MemberErrorCode -import roomescape.member.exception.MemberException -import roomescape.member.infrastructure.persistence.MemberEntity -import roomescape.member.infrastructure.persistence.MemberRepository -import roomescape.member.infrastructure.persistence.Role -import roomescape.util.MemberFixture -import roomescape.util.TsidFactory - -class MemberWriterTest : FunSpec({ - val memberRepository: MemberRepository = mockk() - val memberValidator = MemberValidator(memberRepository) - val memberWriter = MemberWriter(TsidFactory, memberValidator, memberRepository) - - context("create") { - val name = "name" - val email = "email" - val password = "password" - val role = Role.MEMBER - - test("중복된 이메일이 있으면 실패한다.") { - every { - memberRepository.existsByEmail(any()) - } returns true - - shouldThrow { - memberWriter.create(name, email, password, role) - }.also { - it.errorCode shouldBe MemberErrorCode.DUPLICATE_EMAIL - } - } - - test("중복된 이메일이 없으면 저장한다.") { - every { - memberRepository.existsByEmail(any()) - } returns false - - every { - memberRepository.save(any()) - } returns MemberFixture.create( - name = name, - account = email, - password = password, - role = role - ) - - memberWriter.create(name, email, password, role) - - verify(exactly = 1) { - memberRepository.save(any()) - } - } - } -}) diff --git a/src/test/kotlin/roomescape/member/infrastructure/persistence/MemberRepositoryTest.kt b/src/test/kotlin/roomescape/member/infrastructure/persistence/MemberRepositoryTest.kt deleted file mode 100644 index d5af4d07..00000000 --- a/src/test/kotlin/roomescape/member/infrastructure/persistence/MemberRepositoryTest.kt +++ /dev/null @@ -1,63 +0,0 @@ -package roomescape.member.infrastructure.persistence - -import io.kotest.core.spec.style.FunSpec -import io.kotest.matchers.nulls.shouldNotBeNull -import io.kotest.matchers.shouldBe -import jakarta.persistence.EntityManager -import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest -import roomescape.util.MemberFixture - -@DataJpaTest(showSql = true) -class MemberRepositoryTest( - val entityManager: EntityManager, - val memberRepository: MemberRepository -) : FunSpec({ - context("existsByEmail") { - val account = "email" - val email = "$account@email.com" - - beforeTest { - entityManager.persist(MemberFixture.create(account = account)) - entityManager.flush() - entityManager.clear() - } - - test("동일한 이메일이 있으면 true 반환") { - val result = memberRepository.existsByEmail(email) - result shouldBe true - } - - test("동일한 이메일이 없으면 false 반환") { - memberRepository.existsByEmail(email.substring(email.length - 1)) shouldBe false - } - } - - context("findByEmailAndPassword") { - val account = "email" - val email = "$account@email.com" - val password = "password123" - - beforeTest { - entityManager.persist(MemberFixture.create(account = account, password = password)) - entityManager.flush() - entityManager.clear() - } - - test("둘다 일치하면 정상 반환") { - memberRepository.findByEmailAndPassword(email, password) shouldNotBeNull { - this.email shouldBe email - this.password shouldBe password - } - } - - test("이메일이 틀리면 null 반환") { - val invalidMail = email.substring(email.length - 1) - memberRepository.findByEmailAndPassword(invalidMail, password) shouldBe null - } - - test("비밀번호가 틀리면 null 반환") { - val invalidPassword = password.substring(password.length - 1) - memberRepository.findByEmailAndPassword(email, invalidPassword) shouldBe null - } - } -}) diff --git a/src/test/kotlin/roomescape/schedule/ScheduleApiTest.kt b/src/test/kotlin/roomescape/schedule/ScheduleApiTest.kt index 25ae6bc0..353ed95f 100644 --- a/src/test/kotlin/roomescape/schedule/ScheduleApiTest.kt +++ b/src/test/kotlin/roomescape/schedule/ScheduleApiTest.kt @@ -290,7 +290,7 @@ class ScheduleApiTest( val themeId: Long = Given { contentType(MediaType.APPLICATION_JSON_VALUE) header("Authorization", "Bearer $token") - body(ThemeFixtureV2.createRequest.copy(name = "theme-${System.currentTimeMillis()}")) + body(ThemeFixture.createRequest.copy(name = "theme-${System.currentTimeMillis()}")) } When { post("/admin/themes") } Extract { @@ -616,7 +616,7 @@ class ScheduleApiTest( Given { contentType(MediaType.APPLICATION_JSON_VALUE) header("Authorization", "Bearer $token") - body(ThemeFixtureV2.createRequest.copy(name = "theme-${System.currentTimeMillis()}")) + body(ThemeFixture.createRequest.copy(name = "theme-${System.currentTimeMillis()}")) } When { post("/admin/themes") } Extract { diff --git a/src/test/kotlin/roomescape/theme/ThemeApiTest.kt b/src/test/kotlin/roomescape/theme/ThemeApiTest.kt index d397f659..4d27c89a 100644 --- a/src/test/kotlin/roomescape/theme/ThemeApiTest.kt +++ b/src/test/kotlin/roomescape/theme/ThemeApiTest.kt @@ -19,18 +19,18 @@ import roomescape.theme.business.MIN_DURATION import roomescape.theme.business.MIN_PARTICIPANTS import roomescape.theme.business.MIN_PRICE import roomescape.theme.exception.ThemeErrorCode -import roomescape.theme.infrastructure.persistence.v2.ThemeEntityV2 -import roomescape.theme.infrastructure.persistence.v2.ThemeRepositoryV2 -import roomescape.theme.web.ThemeCreateRequestV2 +import roomescape.theme.infrastructure.persistence.ThemeEntity +import roomescape.theme.infrastructure.persistence.ThemeRepository +import roomescape.theme.web.ThemeCreateRequest import roomescape.theme.web.ThemeUpdateRequest import roomescape.util.FunSpecSpringbootTest -import roomescape.util.ThemeFixtureV2.createRequest +import roomescape.util.ThemeFixture.createRequest import roomescape.util.assertProperties import roomescape.util.runTest import kotlin.random.Random class ThemeApiTest( - private val themeRepository: ThemeRepositoryV2 + private val themeRepository: ThemeRepository ) : FunSpecSpringbootTest() { @@ -146,7 +146,7 @@ class ThemeApiTest( } ).also { val createdThemeId: Long = it.extract().path("data.id") - val createdTheme: ThemeEntityV2 = themeRepository.findByIdOrNull(createdThemeId) + val createdTheme: ThemeEntity = themeRepository.findByIdOrNull(createdThemeId) ?: throw AssertionError("Unexpected Exception Occurred.") createdTheme.name shouldBe createRequest.name @@ -376,7 +376,7 @@ class ThemeApiTest( context("관리자 페이지에서 특정 테마의 상세 정보를 조회한다.") { test("정상 응답") { - val createdTheme: ThemeEntityV2 = createDummyTheme(createRequest) + val createdTheme: ThemeEntity = createDummyTheme(createRequest) runTest( token = loginUtil.loginAsAdmin(), @@ -445,7 +445,7 @@ class ThemeApiTest( context("테마를 수정한다.") { lateinit var token: String - lateinit var createdTheme: ThemeEntityV2 + lateinit var createdTheme: ThemeEntity lateinit var apiPath: String val updateRequest = ThemeUpdateRequest(name = "modified") @@ -671,7 +671,7 @@ class ThemeApiTest( } } - fun createDummyTheme(request: ThemeCreateRequestV2): ThemeEntityV2 { + fun createDummyTheme(request: ThemeCreateRequest): ThemeEntity { val createdThemeId: Long = Given { contentType(MediaType.APPLICATION_JSON_VALUE) header("Authorization", "Bearer ${loginUtil.loginAsAdmin()}") diff --git a/src/test/kotlin/roomescape/util/Fixtures.kt b/src/test/kotlin/roomescape/util/Fixtures.kt index d1a738d5..a4b4a594 100644 --- a/src/test/kotlin/roomescape/util/Fixtures.kt +++ b/src/test/kotlin/roomescape/util/Fixtures.kt @@ -1,14 +1,17 @@ package roomescape.util +import com.github.f4b6a3.tsid.TsidFactory import roomescape.member.infrastructure.persistence.MemberEntity import roomescape.member.infrastructure.persistence.Role import roomescape.schedule.web.ScheduleCreateRequest -import roomescape.theme.infrastructure.persistence.v2.Difficulty -import roomescape.theme.web.ThemeCreateRequestV2 +import roomescape.theme.infrastructure.persistence.Difficulty +import roomescape.theme.web.ThemeCreateRequest import java.time.LocalDate import java.time.LocalTime -object MemberFixtureV2 { +val tsidFactory = TsidFactory(0) + +object MemberFixture { val admin: MemberEntity = MemberEntity( _id = 9304, name = "ADMIN", @@ -26,8 +29,8 @@ object MemberFixtureV2 { ) } -object ThemeFixtureV2 { - val createRequest: ThemeCreateRequestV2 = ThemeCreateRequestV2( +object ThemeFixture { + val createRequest: ThemeCreateRequest = ThemeCreateRequest( name = "Matilda Green", description = "constituto", thumbnailUrl = "https://duckduckgo.com/?q=mediocrem", diff --git a/src/test/kotlin/roomescape/util/RestAssuredUtils.kt b/src/test/kotlin/roomescape/util/RestAssuredUtils.kt index 78c77e16..ab83a651 100644 --- a/src/test/kotlin/roomescape/util/RestAssuredUtils.kt +++ b/src/test/kotlin/roomescape/util/RestAssuredUtils.kt @@ -21,7 +21,7 @@ class LoginUtil( if (!memberRepository.existsByEmail(email)) { memberRepository.save( MemberEntity( - _id = TsidFactory.next(), + _id = tsidFactory.next(), email = email, password = password, name = email.split("@").first(), @@ -43,11 +43,11 @@ class LoginUtil( } fun loginAsAdmin(): String { - return login(MemberFixtureV2.admin.email, MemberFixtureV2.admin.password, Role.ADMIN) + return login(MemberFixture.admin.email, MemberFixture.admin.password, Role.ADMIN) } fun loginAsUser(): String { - return login(MemberFixtureV2.user.email, MemberFixtureV2.user.password) + return login(MemberFixture.user.email, MemberFixture.user.password) } } diff --git a/src/test/kotlin/roomescape/util/RoomescapeApiTest.kt b/src/test/kotlin/roomescape/util/RoomescapeApiTest.kt deleted file mode 100644 index aaa2af4c..00000000 --- a/src/test/kotlin/roomescape/util/RoomescapeApiTest.kt +++ /dev/null @@ -1,145 +0,0 @@ -package roomescape.util - -import com.fasterxml.jackson.databind.ObjectMapper -import com.github.f4b6a3.tsid.TsidFactory -import com.ninjasquad.springmockk.MockkBean -import com.ninjasquad.springmockk.SpykBean -import io.kotest.core.spec.style.BehaviorSpec -import io.mockk.every -import org.springframework.boot.test.context.TestConfiguration -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Import -import org.springframework.context.annotation.Primary -import org.springframework.data.jpa.mapping.JpaMetamodelMappingContext -import org.springframework.http.HttpHeaders -import org.springframework.http.MediaType -import org.springframework.test.web.servlet.* -import roomescape.auth.exception.AuthErrorCode -import roomescape.auth.exception.AuthException -import roomescape.auth.infrastructure.jwt.JwtHandler -import roomescape.auth.web.support.AuthInterceptor -import roomescape.auth.web.support.MemberIdResolver -import roomescape.common.config.JacksonConfig -import roomescape.common.log.ApiLogMessageConverter -import roomescape.member.exception.MemberErrorCode -import roomescape.member.exception.MemberException -import roomescape.member.implement.MemberFinder -import roomescape.member.infrastructure.persistence.MemberEntity -import roomescape.member.infrastructure.persistence.MemberRepository -import roomescape.util.MemberFixture.NOT_LOGGED_IN_USERID - -@Import(TestConfig::class, JacksonConfig::class) -@MockkBean(JpaMetamodelMappingContext::class) -abstract class RoomescapeApiTest : BehaviorSpec() { - - @SpykBean - private lateinit var authInterceptor: AuthInterceptor - - @SpykBean - private lateinit var memberIdResolver: MemberIdResolver - - @MockkBean - private lateinit var memberRepository: MemberRepository - - @SpykBean - lateinit var apiLogMessageConverter: ApiLogMessageConverter - - @SpykBean - lateinit var memberFinder: MemberFinder - - @MockkBean - lateinit var jwtHandler: JwtHandler - - val objectMapper: ObjectMapper = JacksonConfig().objectMapper() - val admin: MemberEntity = MemberFixture.admin() - val user: MemberEntity = MemberFixture.user() - - fun runGetTest( - mockMvc: MockMvc, - endpoint: String, - log: Boolean = false, - assert: MockMvcResultMatchersDsl.() -> Unit - ): ResultActionsDsl = mockMvc.get(endpoint) { - header(HttpHeaders.AUTHORIZATION, "Bearer token") - }.apply { - log.takeIf { it }?.let { this.andDo { print() } } - }.andExpect(assert) - - fun runPostTest( - mockMvc: MockMvc, - endpoint: String, - body: Any? = null, - log: Boolean = false, - assert: MockMvcResultMatchersDsl.() -> Unit - ): ResultActionsDsl = mockMvc.post(endpoint) { - this.header(HttpHeaders.AUTHORIZATION, "Bearer token") - body?.let { - this.contentType = MediaType.APPLICATION_JSON - this.content = objectMapper.writeValueAsString(it) - } - }.apply { - log.takeIf { it }?.let { this.andDo { print() } } - }.andExpect(assert) - - fun runDeleteTest( - mockMvc: MockMvc, - endpoint: String, - log: Boolean = false, - assert: MockMvcResultMatchersDsl.() -> Unit - ): ResultActionsDsl = mockMvc.delete(endpoint) { - header(HttpHeaders.AUTHORIZATION, "Bearer token") - }.apply { - log.takeIf { it }?.let { this.andDo { print() } } - }.andExpect(assert) - - fun loginAsAdmin() { - every { - jwtHandler.getMemberIdFromToken(any()) - } returns admin.id!! - - every { memberFinder.findById(admin.id!!) } returns admin - } - - fun loginAsUser() { - every { - jwtHandler.getMemberIdFromToken(any()) - } returns user.id!! - - every { memberFinder.findById(user.id!!) } returns user - } - - fun doNotLogin() { - every { - jwtHandler.getMemberIdFromToken(any()) - } throws AuthException(AuthErrorCode.INVALID_TOKEN) - - every { - memberFinder.findById(NOT_LOGGED_IN_USERID) - } throws MemberException(MemberErrorCode.MEMBER_NOT_FOUND) - } - - fun MvcResult.readValue(valueType: Class): T = this.response.contentAsString - .takeIf { it.isNotBlank() } - ?.let { readValue(it, valueType) } - ?: throw RuntimeException( - """ - [Test] Exception occurred while reading response json: ${this.response.contentAsString} with value type: $valueType - """.trimIndent() - ) - - fun readValue(responseJson: String, valueType: Class): T = objectMapper - .readTree(responseJson)["data"] - ?.let { objectMapper.convertValue(it, valueType) } - ?: throw RuntimeException( - """ - [Test] Exception occurred while reading response json: $responseJson with value type: $valueType - """.trimIndent() - ) -} - -@TestConfiguration -class TestConfig { - @Bean - @Primary - fun tsidFactory(): TsidFactory = TsidFactory -} \ No newline at end of file