본문 바로가기

코틀린

코루틴 테스트시 mockMvc에서 response가 비어있을때

        @Test
        @DisplayName("특정주식의 레포트를 출력할수있다")
        fun getStockReport() {
            runTest {
                val mvcResult =
                    mvc
                        .perform(
                            MockMvcRequestBuilders
                                .get("/api/report/stock?stockName=삼성전자")
                                .contentType(MediaType.APPLICATION_JSON),
                        ).andExpect(status().isOk)
                        .andExpect(request().asyncStarted()) //이거추가
                        .andExpect( //여기서 검증
                            request()
                                .asyncResult(
                                    Result(
                                        ResponseReportDto(
                                            "삼성전자 report",
                                            CustomDateTimeMock(TestConstant.TEST_CURRENT_TIME).getNow(),
                                        ),
                                    ),
                                ),
                        ).andReturn()
            }
        }

Expect에서 검증해야함

이떄 request나 status도 그렇고,다 org.springframework.test.web.servlet.result.MockMvcResultMatchers패키지의 함수들인데,인텔리제이에서 인텔리센스로 잘 못불러오는거같음,그냥 안떠도 끝까지 치면 나옴

 

응용으로,만약 저런식으로 비교하기 힘든 배열같은경우,mvc.perform을 2번써서 해결할수있음

@Test
@DisplayName("거래량상위주식의 레포트를 출력할수있다")
fun getHighStockReport() {
    runTest {
        val mvcResult = //여기서 api통신후 생성하고
            mvc
                .perform(
                    MockMvcRequestBuilders
                        .get("/api/report/stock/high")
                        .contentType(MediaType.APPLICATION_JSON),
                ).andExpect(request().asyncStarted()) //이건필수
                .andReturn()

        mvc //여기서 검증
            .perform(asyncDispatch(mvcResult))
            .andExpect(status().isOk)
            .andExpect(jsonPath("$.data", hasSize<Any>(10)))
            .andExpect(jsonPath("$.data[*].report", hasItem("LG전자 report")))
        
    }
}

즉 assert문을 mvc로 처리하는식으로 처리할수있음

이때 jsonPath를 사용해야하는데,

// 배열 크기 검증
.andExpect(jsonPath("$.items", hasSize<Any>(3)))

// 배열 내 특정 값 포함 여부
.andExpect(jsonPath("$.items", hasItem("value")))

// 배열 내 모든 요소 검증
.andExpect(jsonPath("$.items[*].name", everyItem(startsWith("test"))))

// 특정 조건을 만족하는 요소 검증
.andExpect(jsonPath("$.items[?(@.price > 1000)]", hasSize<Any>(2)))

// null 체크
.andExpect(jsonPath("$.optional").value(nullValue()))

// 숫자 범위 체크
.andExpect(jsonPath("$.value", allOf(
    greaterThan(0),
    lessThan(100)
)))

이렇게 사용할수있고,커스텀 matcher를 만들수도있음

fun isValidReport() = object : Matcher<String> {
    override fun matches(actual: Any): Boolean {
        val report = actual as String
        return report.contains("삼성전자") && 
               report.length > 100 &&
               report.contains("주가")
    }
}

// 사용
.andExpect(jsonPath("$.report", isValidReport()))