Testing Codes/MockK

[MockK] MockK 란 무엇인가? Gradle 사용해 MockK 개발 환경 설정하고 테스트 만들어보기

MockK란 무엇인가?

MockK는 코틀린에서 테스트 시 목(Mock) 객체를 생성하는 것을 돕는 라이브러리이다. 기존에 목 객체를 만들기 위해서는 인터페이스를 목 클래스로 직접 구현을 해야 했는데, MockK를 사용하면 간단하게 목 객체를 생성할 수 있다.

 

Gradle에 MockK 의존성 추가하기 

Gradle에 MockK에 대한 의존성은 다음과 같이 추가해주면 된다.

dependencies {
    ...
    // MockK 라이브러리
    testImplementation("io.mockk:mockk:1.13.8")
}

 

MockK의 사용

MockK를 사용하는 것은 매우 간단하다. 예를 들어 다음과 같은 UserProfileFetcher이 있다고 해보자.

class UserProfileFetcher(
    private val userRepository: UserRepository,
    private val contactRepository: ContactRepository
) {
    fun getUserProfileById(id: String): UserProfile {
        return UserProfile(
            id = id,
            name = userRepository.getNameByUserId(id),
            phoneNumber = contactRepository.getPhoneNumberByUserId(id)
        )
    }
}

UserProfileFetcher은 UserRepository와 ContactRepository에 대한 의존성을 가지므로, UserProfileFetcher을 테스트 하기 위해서는 이 두 객체를 주입해주어야 한다. MockK를 사용하지 않고 이 두 객체를 주입하기 위해서는 이 두 객체를 모방하는 Test Doubles를 직접 만들어 주입해주어야 하지만, MockK를 사용하면 다음과 같이 매우 간단하게 주입할 수 있다.

class UserProfileFetcherTest {
    @Test
    fun testInteraction() {
        // Given
        val userRepository : UserRepository = mockk()
        val contactRepository : ContactRepository = mockk()
        val userProfileFetcher = UserProfileFetcher(
            userRepository = userRepository,
            contactRepository = contactRepository
        )
        ...
    }
}

목 객체를 만들고 싶은 객체에 대해 mockk 함수를 사용하는 것 만으로 목 객체를 만들 수 있다. 물론 이렇게 만든 목 객체는 아무런 동작을 하지 못한다. 만들어진 목 객체가 특정한 동작을 하도록 만들고 싶으면 별도의 동작을 설정해야 한다. 예를 들어 UserRepository의 getUserNameById을 호출 했을 때 언제나 'TestUser'을 반환하도록 만들고, ContactRepository의 getPhoneNumberByUserId을 호출 했을 때 언제나 '010-xxxx-xxxx'를 반환하도록 만들고 싶으면 다음과 같이 쓰면 된다.

class UserProfileFetcherTest {
    @Test
    fun testInteraction() {
        // Given
        val userRepository : UserRepository = mockk()
        val contactRepository : ContactRepository = mockk()
        val userProfileFetcher = UserProfileFetcher(
            userRepository = userRepository,
            contactRepository = contactRepository
        )
        every { userRepository.getNameByUserId(any()) }.returns("TestUser")
        every { contactRepository.getPhoneNumberByUserId(any()) }.returns("010-xxxx-xxxx")

        // When
        val userProfile = userProfileFetcher.getUserProfileById("test")

        // Then
        assertEquals("TestUser", userProfile.name)
        assertEquals("010-xxxx-xxxx", userProfile.phoneNumber)
    }
}

이 테스트에서는 UserProfileFetcher을 사용해 유저 프로필을 가져온 후 이름과, 휴대전화번호가 예상된대로 반환되는지 확인하는 테스트를 진행한다. UserProfileFetcher는 유저의 이름을 UserRepository로부터 가져오고 휴대전화번호를 ContactRepository로부터 가져오므로, 코드를 실행해보면 테스트가 통과되는 것을 볼 수 있다.

그림1. 테스트 통과

 

반응형

 

이 글의 저작권은 Dev World 에 있습니다. 글, 이미지 무단 재배포 및 변경을 금지합니다.

 

 

Kotlin, Android, Spring 사용자 오픈 카톡

오셔서 궁금한 점을 질문해보세요!
비밀번호 : kotlin22

open.kakao.com