: 결제 API의 컨트롤러 역할을 하며, 클라이언트의 요청을 받아 처리하는 부분
@RequestMapping("/api/v1")
@RestController
class PaymentController(
private val paymentService: PaymentService // 선언하면서 프로퍼티를 선언하면 스프링이 알아서 의존성을 주입해줌
) {
@PostMapping("/pay")
fun pay(
@Valid @RequestBody
payRequest: PayRequest
): PayResponse {
return PayResponse("p1", 100, "txId", LocalDateTime.now())
}
}
data class PayResponse(
val payUserId: String,
val amount: Long,
val transactionId: String,
val transactedAt: LocalDateTime,
)
data class PayRequest(
@field:NotBlank
val payUserId: String,
@field:Min(100)
val amount: Long,
@field:NotBlank
val merchantTransactionId: String,
@field:NotBlank
val orderTitle: String,
)
private val paymentService: PaymentService : kotlin에서는 클래스 선언 시 괄호 안에 생성자를 정의하므로 PaymentService는 생성자 주입 방식으로 spring이 PaymentService의 의존성을 자동으로 주입Request와 Response DTO를 선언해줌💡 Kotlin의 데이터 클래스
자동으로 equals(), hashCode(), toString(), copy() 등을 제공하여 간결한 코드를 작성할 수 있게 합니다. (DTO나 VO 같은 데이터 전달 객체를 정의할 때 특히 유용!!)
@field: 검증 어노테이션에 붙이지않으면 생성자에서만 검증해주므로 필드 레벨까지 검증할수있도록 명시해줌test code 작성전 test code 작성시 필요한 의존성을 추가해줍니다.
kotlin을 이용한 테스트코드에서는 Mocking을 위해
mock 대신 mockk을 사용합니다.
testImplementation("io.mockk:mockk:1.13.3")
testImplementation("com.ninja-squad:springmockk:4.0.0")
‼️ 참고 -> mockk 공식문서
@WebMvcTest(PaymentController::class)
internal class PaymentControllerTest @Autowired constructor(
private val mockMvc: MockMvc
) {
@MockkBean
private lateinit var paymentService: PaymentService
private val mapper = ObjectMapper()
@Test
fun `결제 요청 - 성공 응답`() {
//given
//when
//then
mockMvc.post("/api/v1/pay") {
headers {
contentType = APPLICATION_JSON
accept = listOf(APPLICATION_JSON)
}
content = mapper.writeValueAsString(
PayRequest(
payUserId = "p1",
amount = 100,
merchantTransactionId = "m1",
orderTitle = "orderTitle"
)
)
}.andExpect {
status { isOk() }
content { jsonPath("$.payUserId", equalTo("p1")) }
content { jsonPath("$.amount", equalTo(100)) }
content { jsonPath("$.transactionId", equalTo("txId")) }
}.andDo { print() }
}
}
MockMvc:실제로 애플리케이션을 실행하지 않고도 컨트롤러의 엔드포인트를 테스트할 수 있음.@MockkBean : 테스트 중에 실제 빈 대신 모킹된 빈을 사용하도록 설정하는 어노테이션, PaymentController가 실제 PaymentService 구현체를 호출하지 않고 모킹된 객체를 사용해 테스트를 진행함private val mapper = ObjectMapper() : PayRequest 객체를 JSON 문자열로 변환해 요청의 본문(content)에 포함시키기 위해 사용함POST 요청 시뮬레이션: mockMvc.post("/api/v1/pay")는 /api/v1/pay 엔드포인트로 POST 요청을 보내는 테스트 코드헤더 설정: contentType = APPLICATION_JSON과 accept = listOf(APPLICATION_JSON)로 헤더에 JSON 타입을 설정본문 내용 설정: mapper.writeValueAsString()을 사용해 PayRequest 객체를 JSON 형식으로 직렬화하여 요청 본문(content)에 포함status { isOk() }: HTTP 상태 코드가 200(OK)임을 검증jsonPath()는 JSON 응답에서 특정 경로의 값을 추출하는 방법.andDo { print() } : 테스트 중 발생한 요청과 응답을 출력테스트를 실행하여 출력결과를 보면 성공적으로 요청을하고 응답을 받는것을 확인하실 수 있습니다.
