본문 바로가기
업무 기록/ETC

테스트 코드 작성 이유 및 방법 - SpringBoot, Kotlin

by code2772 2024. 8. 9.

[ 목차 ]

    728x90
    반응형

     

    <내가 생각하는 테스트 코드 작성 이유>

     

    테스트 코드의 장점은 다양하다 그 중 내가 생각하는 가장 큰 이유는 여러명이 프로젝트를 작업하는 경우에 있다. 각자의 코드를 변경한 경우 연관된 코드로 문제가 발생할 수 있다. 문제를 방지하기 위해 코드 변경 시마다 테스트를 일일히 하기에는 문제가 있어 테스트 코드를 작성하여 변경 시마다 자동으로 테스트가 실행되도록 설정하고 안정성과 효율성을 크게 향상시킬 수 있는 측면이다.

     

     


    <사전지식/내용>

     

    @Mock:

    Mockito를 사용하여 가짜 객체(mock)를 생성합니다. 여기서는 rcsBrandRepository의 가짜 객체를 생성하여 실제 데이터베이스 연결 없이 테스트할 수 있게 합니다. 

     


    @InjectMocks: 

    가짜 객체를 자동으로 주입합니다. 여기서는 rcsBrandServiceImpl에 mock 객체들을 주입합니다.

     


    @BeforeEach:

     각 테스트 메서드 실행 전에 실행될 설정을 정의합니다. 여기서는 MockitoAnnotations.openMocks(this)를 호출하여 각 테스트마다 새로운 상태의 mock 객체들을 사용할 수 있게 합니다.

     

     

     <테스트 토드 작성 방식>

     

    Given (주어진 상황):
    테스트를 위한 초기 조건이나 상태를 설정합니다.
    테스트에 필요한 객체들을 준비하고 초기화합니다.


    When (실행):
    테스트하고자 하는 실제 동작이나 기능을 실행합니다.
    주로 테스트 대상 메서드를 호출하는 부분입니다.


    Then (결과 확인):
    실행 결과를 검증합니다.
    예상한 결과와 실제 결과를 비교하여 테스트의 성공 여부를 판단합니다.

     


    <테스트 코드 예시>

    class RcsBrandServiceImplTest {
    
        @Mock
        // Mock 어노테이션은 Mockito 사용하여 가짜 객체(mock)을 생성
        // rcsBrandRepository 의 가짜 객체 생성하여  실제 DB 연결 없이 테스트 가능
        private lateinit var rcsBrandRepository: RcsBrandRepository
    
        @InjectMocks
        // InjectMocks 은 가짜 객체 자동 주입한다.
        private lateinit var rcsBrandServiceImpl: RcsBrandServiceImpl
    
        @BeforeEach
        // BeforeEach 각 테스트 메서드 실행 전 실행될 설정 정의 기능
        fun setup(){
            MockitoAnnotations.openMocks(this)
            // MockitoAnnotations.openMocks(this) 각 테스트마다 새로운 상태의 mock 객체들을 사용할 수 있다.
        }
    
        @Test
        @DisplayName("브랜드 값 전체 조회 내림차순")
        fun `test getAllRcsBrands`(){
    
            // Given : 테스트 필요한 초기 조건 설정
            val pageable = PageRequest.of(0,10)
    
            val now = LocalDateTime.now()
            val mockBrands = listOf(
                RcsBrand(1, "brand1", "key1", "Brand1", "user1", now, now, now,"ACTIVE"),
                RcsBrand(2, "brand2", "key2", "Brand2", "user2", now, now, now,"ACTIVE")
            )
            val mockPage: Page<RcsBrand> = PageImpl(mockBrands)
    
            // when : 해당 JPA 호출 시 mockPage 반환
            `when`(rcsBrandRepository.findAllByOrderByRegisterDateDesc(pageable)).thenReturn(mockPage)
            val result = rcsBrandServiceImpl.getAllRcsBrands(pageable)
    
            // then : 테스트 결과 검증 -> 반환된 결과가 예상한 mockpage와 일치하는지 확인
            assertEquals(mockPage, result)
            verify(rcsBrandRepository).findAllByOrderByRegisterDateDesc(pageable)
    
        }

     

     

    위 테스트는 getAllRcsBrands 메서드를 검증합니다:

    • Given: 테스트에 필요한 초기 조건을 설정합니다.
    • When: 실제 테스트할 동작을 수행합니다. 여기서는 rcsBrandRepository.findAllByOrderByRegisterDateDesc가 호출될 때 mockPage를 반환하도록 설정하고, 실제 메서드를 호출합니다.
    • Then: 테스트 결과를 검증합니다. 반환된 결과가 예상한 mockPage와 일치하는지 확인하고, 메서드가 실제로 호출되었는지 verify합니다.

     

     

    이 후 테스트를 실행하면 하단과 같이 결과를 확인할 수 있다.

     

    반응형