Retrofit Api 단위테스트 (Mockk 사용)

Seok-woo Kim·2021년 6월 4일
0

안드로이드

목록 보기
4/10

1. 시작

1) 계기

프로젝트 완료 후 일이 없어 리팩터링과 함께 ViewModel에 대해서만이라도 단위테스트 클래스를 작성해놓자 생각이 들어 시작하게됨

2) 의존성

testImplementation "io.mockk:mockk:1.11.0"
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.5.0'
testImplementation "androidx.arch.core:core-testing:2.1.0"

2. 테스트 작성

1) ApiService, DataSource, Repository

보통 Retrofit으로 Api연동을 할때, Retrofit 어노테이션을 쓰는 interface 서비스를 작성하고, DataSource(Remote) -> Repository 순으로 의존성을 주입한 뒤 ViewModel에서는 Repository만 주입하고 사용할 것 이다.

2) Mock 객체 생성

이제 Api Response를 줄 Api 객체가 필요한데, 위에 3개 모두 Mock을 생성할 필요는 없고 가장 근본이되는 Service만 mockk<>()로 생성한 후 순서대로 주입해주면 된다.

private val userService = mockk<UserService>()
private val userDataSource = RemoteUserDataSource(userService)
private val userRepository = UserRepository(userDataSource)

3) Mock 객체 리턴 값

mockk를 사용해 Mock객체를 만들면 Mock객체의 변수나 함수가 return하는 값을 Test시 지정해 줘야한다. mockk 라이브러리에서 제공하는 every, coEvery라는 함수 블럭에 Mock객체의 변수나 함수를 넣고 returns라는 함수로 임의의 결과값을 설정한다.

이때 suspend fun을 사용하는 함수의 경우 Coroutine에서 실행해야 하기때문에 coEvery 블럭에 함수를 넣어준다.

    coEvery {
        userService.getUsers() 
    } returns Response.success(Users(
            code = 200,
            success = true,
            users = listOf(
            	User(name = "A", email = "@"),
                User(name = "B", email = "@"),
                User(name = "C", email = "@")
            )
        )
    )

4) 테스트 실행

coEvery 혹은 every 블럭과 returns로 변수나 함수에 대한 반환값을 설정했다면, 해당 변수나 함수 실행시 반환값으로 임의설정값을 돌려줄 것이다.

@Test
fun getUsers() {
    runBlockingTest {
    	userRepository.getUsers()
    }
}

ApiServiceInterface -> DataSource -> Repository 순으로 의존성이 주입되기 때문에,
Interface만 Mock객체 설정 후 실제 테스트 시에는 Repository로 함수를 테스트하면 된다.

3. 끝

Context랑 동시성 함수들때문에 Test작성하기 힘들다. 끝.

profile
안드로이드 개발자 (6년 ~ )

0개의 댓글