Skip to content

Commit

Permalink
Merge pull request #56 from ClothingStoreService/refactor/order-test
Browse files Browse the repository at this point in the history
Refactor/order test
  • Loading branch information
axhtl authored Sep 7, 2024
2 parents 8c82be5 + 9aacf5e commit 79c1480
Show file tree
Hide file tree
Showing 8 changed files with 409 additions and 216 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
import org.store.clothstar.kakaoLogin.dto.KakaoRenewTokenResponseDto
import org.store.clothstar.kakaoLogin.dto.KakaoTokenInfoResponseDto
import org.store.clothstar.kakaoLogin.service.KakaoLoginService

@RestController
Expand All @@ -17,21 +15,4 @@ class KakaoController(
fun kakaoCallback(@RequestParam code: String): ResponseEntity<String> {
return ResponseEntity.ok(code)
}

// 토큰 정보 확인
@GetMapping("/auth/kakao/accessInfo")
fun getAccessInfo(@RequestParam accessToken: String): KakaoTokenInfoResponseDto {
val tokenInfo = kakaoLoginService.getTokenInfo(accessToken)
return tokenInfo
}

// 액세스 토큰 갱신 - 유효성 검사 후 토큰 유효기간 만료 시 재로그인 요청
@GetMapping("/auth/kakao/check")
fun checkToken(
@RequestParam accessToken: String,
@RequestParam refreshToken: String
): ResponseEntity<KakaoRenewTokenResponseDto> {
val renewTokenInfo: KakaoRenewTokenResponseDto = kakaoLoginService.validateToken(accessToken, refreshToken)
return ResponseEntity.ok(renewTokenInfo)
}
}

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import org.springframework.util.LinkedMultiValueMap
import org.springframework.util.MultiValueMap
import org.springframework.web.reactive.function.BodyInserters
import org.springframework.web.reactive.function.client.WebClient
import org.store.clothstar.kakaoLogin.dto.KakaoRenewTokenResponseDto
import org.store.clothstar.kakaoLogin.dto.KakaoTokenInfoResponseDto
import org.store.clothstar.kakaoLogin.dto.KakaoTokenResponseDto
import org.store.clothstar.kakaoLogin.dto.KakaoUserInfoResponseDto

Expand Down Expand Up @@ -86,59 +84,4 @@ class KakaoLoginService {
logger.info { "email : ${userInfo.kakaoAccount!!.email}" }
return userInfo
}

// 토큰 유효성 검사
fun validateToken(accessToken: String, refreshToken: String): KakaoRenewTokenResponseDto {
return try {
getTokenInfo(accessToken)
// 액세스 토큰이 유효한 경우 토큰 갱신
refreshAccessToken(refreshToken)
} catch (e: Exception) {
// getTokenInfo에서 예외가 발생한 경우 재로그인 필요
throw Exception("Access Token이 만료되었습니다. 재로그인이 필요합니다.")
}
}

// 토큰 정보 보기
fun getTokenInfo(accessToken: String): KakaoTokenInfoResponseDto {
val response = WebClient.create("https://kapi.kakao.com")
.get()
.uri("/v1/user/access_token_info")
.header("Authorization", "Bearer $accessToken")
.retrieve()
.bodyToMono(String::class.java)
.block()

val objectMapper = ObjectMapper()
val tokenInfo: KakaoTokenInfoResponseDto =
objectMapper.readValue(response, KakaoTokenInfoResponseDto::class.java)

logger.info { "Access Token 만료기한 : ${tokenInfo.expiresIn}" }
return tokenInfo
}

// 리프레시 토큰으로 액세스 토큰 갱신
fun refreshAccessToken(refreshToken: String): KakaoRenewTokenResponseDto {
val params: MultiValueMap<String, String> = LinkedMultiValueMap()
params.add("grant_type", "refresh_token")
params.add("client_id", clientId)
params.add("refresh_token", refreshToken)
params.add("client_secret", clientSecret)

val response = WebClient.create("https://kauth.kakao.com")
.post()
.uri(tokenUri)
.body(BodyInserters.fromFormData(params))
.header("Content-Type", "application/x-www-form-urlencoded;charset=utf-8")
.retrieve()
.bodyToMono(String::class.java)
.block()

val objectMapper = ObjectMapper()
val kakaoToken: KakaoRenewTokenResponseDto =
objectMapper.readValue(response, KakaoRenewTokenResponseDto::class.java)

logger.info { "갱신된 Access Token : ${kakaoToken.accessToken}" }
return kakaoToken
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,23 @@ package org.store.clothstar.member.authentication.controller
import com.fasterxml.jackson.databind.ObjectMapper
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.MockWebServer
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.http.MediaType
import org.springframework.test.context.ActiveProfiles
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.*
import org.springframework.transaction.annotation.Transactional
import org.store.clothstar.common.config.redis.RedisUtil
import org.store.clothstar.common.error.ErrorCode
import org.store.clothstar.common.error.exception.InvalidSignupMemberRequest
import org.store.clothstar.common.error.exception.order.OrderNotFoundException
import org.store.clothstar.kakaoLogin.service.KakaoLoginService
import org.store.clothstar.member.authentication.domain.SignUpType
import org.store.clothstar.member.dto.request.KakaoMemberRequest
Expand Down Expand Up @@ -145,4 +150,58 @@ class AuthenticationControllerTest(

mockWebServer.shutdown()
}

@DisplayName("멤버 카카오 회원가입에서 요청DTO가 NULL일 경우 에러처리 테스트")
@Test
fun normalSignUpExceptionTest() {
//kakaoMemberRequest 요청 DTO 생성
val kakaoMemberRequest = KakaoMemberRequest(
name = "Test User",
telNo = "010-1234-5678",
email = null,
code = "test_code"
)

// kakaoMemberRequest를 null로 맞춤
val signUpRequest = SignUpRequest(null, kakaoMemberRequest)
val requestBody = objectMapper.writeValueAsString(signUpRequest)

//when & then
mockMvc.perform(
post(MEMBER_URL)
.param("signUpType", SignUpType.NORMAL.toString())
.contentType(MediaType.APPLICATION_JSON)
.content(requestBody)
)
.andExpect(status().isBadRequest)
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.errorCode").value(400))
.andExpect(jsonPath("$.message").value("회원가입 시 회원 정보가 필요합니다."))
}

@DisplayName("멤버 카카오 회원가입에서 요청DTO가 NULL일 경우 에러처리 테스트")
@Test
fun kakaoSignUpExceptionTest() {
// createMemberRequest 생성을 위한 이메일과 인증번호로 redis 데이터 생성
val email = "[email protected]"
val certifyNum = redisUtil.createdCertifyNum()
redisUtil.createRedisData(email, certifyNum)

// kakaoMemberRequest를 null로 맞춤
val createMemberRequest = CreateObject.getCreateMemberRequest(email, certifyNum)
val signUpRequest = SignUpRequest(createMemberRequest, null)
val requestBody = objectMapper.writeValueAsString(signUpRequest)

//when & then
mockMvc.perform(
post(MEMBER_URL)
.param("signUpType", SignUpType.KAKAO.toString())
.contentType(MediaType.APPLICATION_JSON)
.content(requestBody)
)
.andExpect(status().isBadRequest)
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.errorCode").value(400))
.andExpect(jsonPath("$.message").value("회원가입 시 회원 정보가 필요합니다."))
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.store.clothstar.order

import com.fasterxml.jackson.databind.ObjectMapper
import io.mockk.every
import io.mockk.mockk
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
Expand All @@ -13,8 +15,7 @@ import org.springframework.test.context.ActiveProfiles
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.ResultActions
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.*
import org.springframework.transaction.annotation.Transactional
import org.store.clothstar.category.repository.CategoryJpaRepository
import org.store.clothstar.member.domain.Member
Expand All @@ -33,6 +34,9 @@ import org.store.clothstar.order.dto.request.OrderRequestWrapper
import org.store.clothstar.order.repository.OrderDetailRepository
import org.store.clothstar.order.repository.OrderRepository
import org.store.clothstar.order.util.CreateOrderObject
import org.store.clothstar.product.domain.Item
import org.store.clothstar.product.domain.type.DisplayStatus
import org.store.clothstar.product.domain.type.SaleStatus
import org.store.clothstar.product.repository.ItemRepository
import org.store.clothstar.product.repository.ProductRepository
import java.time.LocalDateTime
Expand Down Expand Up @@ -198,6 +202,82 @@ class OrderUserIntegrationTest(
assertEquals(1, savedOrder.orderDetails.size)
}

@Test
@DisplayName("주문 생성시 상품재고가 0일경우 에러처리 테스트")
fun testCreateOrder_itemStockZeroException() {
//given
val member: Member = memberRepository.save(CreateOrderObject.getMember())
val address = addressRepository.save(CreateOrderObject.getAddress(member))
val category = categoryRepository.save(CreateOrderObject.getCategory())
sellerRepository.save(CreateOrderObject.getSeller(member))
val product = productRepository.save(CreateOrderObject.getProduct(member, category))
val item = itemRepository.save(CreateOrderObject.getItem(product)).apply {
stock = 0
}

val createOrderRequest = CreateOrderRequest(
paymentMethod = PaymentMethod.CARD,
memberId = member.memberId!!,
addressId = address.addressId!!
)
val createOrderDetailRequest = CreateOrderDetailRequest(
productId = product.productId!!,
itemId = item.itemId!!,
quantity = 1
)
val orderRequestWrapper = OrderRequestWrapper(createOrderRequest, createOrderDetailRequest)
val requestBody = objectMapper.writeValueAsString(orderRequestWrapper)

//when & then
val actions: ResultActions = mockMvc.perform(
MockMvcRequestBuilders.post(ORDER_URL)
.contentType(MediaType.APPLICATION_JSON)
.content(requestBody)
)
.andExpect(status().isBadRequest)
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.errorCode").value(400))
.andExpect(jsonPath("$.message").value("품절된 상품입니다."))
}

@Test
@DisplayName("주문 생성시, 주문개수가 상품재고보다 많을 때 재고 부족 예외처리 테스트")
fun testCreateOrder_InsufficientStock_Exception() {
//given
val member: Member = memberRepository.save(CreateOrderObject.getMember())
val address = addressRepository.save(CreateOrderObject.getAddress(member))
val category = categoryRepository.save(CreateOrderObject.getCategory())
sellerRepository.save(CreateOrderObject.getSeller(member))
val product = productRepository.save(CreateOrderObject.getProduct(member, category))
val item = itemRepository.save(CreateOrderObject.getItem(product)).apply {
stock = 1
}

val createOrderRequest = CreateOrderRequest(
paymentMethod = PaymentMethod.CARD,
memberId = member.memberId!!,
addressId = address.addressId!!
)
val createOrderDetailRequest = CreateOrderDetailRequest(
productId = product.productId!!,
itemId = item.itemId!!,
quantity = 5
)
val orderRequestWrapper = OrderRequestWrapper(createOrderRequest, createOrderDetailRequest)
val requestBody = objectMapper.writeValueAsString(orderRequestWrapper)

//when & then
val actions: ResultActions = mockMvc.perform(
MockMvcRequestBuilders.post(ORDER_URL)
.contentType(MediaType.APPLICATION_JSON)
.content(requestBody)
)
.andExpect(status().isBadRequest)
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.errorCode").value(400))
.andExpect(jsonPath("$.message").value("주문 개수가 상품 재고보다 더 많아 요청을 처리할 수 없습니다."))
}

@Test
@DisplayName("주문상세 추가")
fun testAddOrderDetail() {
Expand Down
Loading

0 comments on commit 79c1480

Please sign in to comment.