본문 바로가기
Kotlin

Kotlin - 테스트 코드 어노테이션 및 MockMvc 테스트

by sinabeuro 2024. 1. 10.
728x90

Mock 테스트 주요 어노테이션

//@ActiveProfiles(ProfileConstants.DEVELOPMENT)
//@AutoConfigureMockMvc
//@TestPropertySource(properties = ["spring.profiles.active=develop"])
@WebMvcTest(SlackMessageForwardingController::class)
@ExtendWith(SpringExtension::class)
@Import(MessagingClient::class, WebClientProvider::class)
class SlackMessageForwardingControllerTest(
        @Value("\${spring.config.activate.on-profile}")
        private val profile: String
) {

    @Autowired
    lateinit var mockMvc: MockMvc
    private val hostUrl: String = "http://localhost:8080"
    private val apiUrl: String = "/api/v1/message/test"
    
    @Test
    fun `profile 체크`() {
        println(profile)
    }

    @Test
    fun `slackMessageForwarding api get 호출 성공`() {
        mockMvc.perform(
                MockMvcRequestBuilders.get(hostUrl + apiUrl)
                        .queryParam("channelId", "")
                        .queryParam("alarmMessage", "")
        ).andExpect(
                MockMvcResultMatchers.status().isOk
        ).andDo(MockMvcResultHandlers.print())

    }    
}

 

@ExtendWith(SpringExtension::class) 와 @AutoConfigureMockMvc 는 MockMvc 을 주입하는 역할을 합니다.

둘 중에 하나만 선택해서 사용하면됩니다. 

@ExtendWith(SpringExtension::class) 를 사용하기를 권장.

@AutoConfigureWebMvc 는 사용하면 안될 것 같습니다. @AutoConfigureMockMvc 를 대체해서 사용하면 될 것 같습니다.

 

프로파일을 설정하는 방법

@TestPropertySource(properties = ["spring.profiles.active=develop"])

@SpringBootTest(properties = ["spring.profiles.active=local"])

둘 중에 한가지 방법을 쓰시면 됩니다.

 

반면 이렇게 프로파일 환경을 맞추면 정확히 프로파일이 실행되지 않는다.

@ActiveProfiles(ProfileConstants.DEVELOPMENT)

 

 

Mocking 코드

@ExtendWith(SpringExtension::class)
internal class CommonServiceMockTest {

    private val commonCodeMapper: CommonCodeMapper = mockk()
    private val commonStockMapper: CommonStockMapper = mockk()
    private val commonService: CommonService = CommonService(commonCodeMapper, commonStockMapper)


    @Test
    fun `getCostAndVatTest`() {
        val param = CostAndVatRequestDto(
            stockinYmd = DateUtils.getCurrentDate(DateConstants.YYYY_MM_DD),
            goodsCode = "11231",
            centerCode = "LA02",
            supplierCode = "C08887"
        )

        every {
            commonService.getCostAndVat(param)
        } returns mockk()

        commonService.getCostAndVat(param)

        verify(exactly = 1) {
            commonStockMapper.getCostAndVat(param)
        }
    }

}

 

every {
    stockNoShipResultMapper.updateStockoutMaster(param)
} returns Unit

 

every {
    stockNoShipResultService.getNoShipResultList(params)
} returns List(params.size) { mockk(relaxed = true) }

 

@Test
    fun `wms 오출 실적 조회 테스트`() {
        // given
        val params = listOf(
            StockNoShipResultRequestDto(),
            StockNoShipResultRequestDto(),
            StockNoShipResultRequestDto()
        )
        every {
            stockNoShipResultService.getNoShipResultList(params)
        } returns List(params.size) { mockk(relaxed = true) }

        // when
        val resultList = stockNoShipResultService.getNoShipResultList(params)

        // then
        assertDoesNotThrow {
            assertEquals(params.size, resultList!!.size)
        }
    }

 

@Test
    fun `출고 상세 갱신 테스트`() {
        // given
        val param: StockNoShipResultResponseDto = mockk()
        every {
            stockNoShipResultMapper.updateStockoutDetail(param)
        } returns Unit

        // when
        assertDoesNotThrow {
            stockNoShipResultService.updateStockoutDetail(param)
        }

        // then
        verify (exactly = 1) { stockNoShipResultMapper.updateStockoutDetail(param) }
    }

 

evey 를 통해 의도한 결과값을 설정

verify 를 통해 결과값 검증

 

assertAll 을 통한 복수 검증

assertAll (
    { assertEquals() },
    { assertEquals() },
    { assertEquals() },
)

 


 

DataBase 테스트

 

@Import(value = [DataSourceProvider::class, JpaProvider::class])
@SpringBootApplication(
    scanBasePackageClasses = [OliveyoungDomain::class, OliveyoungInterface::class],
    exclude = [DataSourceAutoConfiguration::class, ErrorMvcAutoConfiguration::class]
)
@Suppress("SpellCheckingInspection")
class DataSourceTestConfiguration {

}

 

@SpringBootTest(
    classes = [DataSourceTestConfiguration::class],
    properties = ["spring.profiles.active = local"]
)
@Tag(TestTagConstants.IGNORE)
internal class CommonServiceTest {

    @Autowired
    lateinit var commonService: CommonService

    @Test
    fun `getCostAndVatTest`() {
        val param = CostAndVatRequestDto(
            stockinYmd =  DateUtils.getCurrentDate(DateConstants.YYYY_MM_DD),
            goodsCode = "11231",
            centerCode = "LA04",
            supplierCode = "C08887"
        )
        commonService.getCostAndVat(param)
    }

}

database 테스트는 assert 으로 검증!

 

 

jsonPath 체크하는 방법

  mvc.perform( MockMvcRequestBuilders
      .get("/employees")
      .accept(MediaType.APPLICATION_JSON)
      .andDo(print())
      .andExpect(status().isOk())
      .andExpect(MockMvcResultMatchers.jsonPath("$.employees").exists())
      .andExpect(MockMvcResultMatchers.jsonPath("$.employees[*].employeeId").isNotEmpty());

출처: https://katfun.tistory.com/entry/Spring-MockMVC를-이용한-Controller-테스트-GET [하고 싶은 것을 즐겁게:티스토리]

 

assertThrows 예시

assert(result2 != null)
verify(exactly = 1) { freebieStandardCodeSequenceRepository.insert(any()) }

freebieAddRequestDto.itemType = Strings.EMPTY
every { freebieItemService.addFreebieItem(any()) } throws Exception("itemType is null")
assertThrows<Exception> { freebieService.addFreebie(freebieAddRequestDto) }

 

 

 

 

@TestInstance(TestInstance.Lifecycle.PER_CLASS)

@TestConstructor(autowireMode = TestConstructor.AutowireMode.ALL)

728x90

'Kotlin' 카테고리의 다른 글

Kotlin - Any 와 * 의 차이  (0) 2023.10.26
Kotlin - 일급 시민(First-class citizen)  (0) 2023.08.08
Kotlin - 다양한 함수  (0) 2023.05.06
Kotlin - 컬렉션  (0) 2023.05.06
코틀린 - Object 함수(Companion)  (0) 2023.05.01

댓글