본문 바로가기

안드로이드

안드로이드 테스팅

반응형

 

 

개발을 하다 보면 Repositrory 혹은 UseCase(domain 레이어를 사용할 경우)에서 로직이 정상적으로 작동하는지 시험해 보고 싶을 때 가 있을 것이다.

이와 관련하여 hilt와 TestDispatcher, mockk등을 이용하여 쉽게 테스팅 코드를 설정하는 법에 대해 알아보자

 

먼저 app단 gradle에 라이브러리를 추가해준다.

 

testImplementation ("com.google.dagger:hilt-android-testing:2.41")
// ...with Kotlin.
kaptTest ("com.google.dagger:hilt-android-compiler:2.41")
// ...with Java.
testAnnotationProcessor ("com.google.dagger:hilt-android-compiler:2.41")

// For instrumented tests.
androidTestImplementation ("com.google.dagger:hilt-android-testing:2.41")
// ...with Kotlin.
kaptAndroidTest ("com.google.dagger:hilt-android-compiler:2.41")
// ...with Java.
androidTestAnnotationProcessor( "com.google.dagger:hilt-android-compiler:2.41")

testImplementation ("org.robolectric:robolectric:4.6.1")

 

class MainTestRunner : AndroidJUnitRunner() {
    override fun newApplication(cl: ClassLoader?, name: String?, context: Context?): Application {
        return super.newApplication(cl, HiltTestApplication::class.java.name, context)
    }
}

 

그리고 AndroidJUnitRunner를 AndroidTest폴더에 작성해 주고 app단 gradle 해당 코드를 추가해 주면 dagger hilt test 관련 설정이 끝난다. (AndroidJUnitRunner대신 Robolectric의 @Configuration 어노테이션을 테스트하는 class위에 작성하여 이용하여는 것도 가능하다. ex)@Config(application = HiltTestApplication::class))

 

defaultConfig {
    ..
    testInstrumentationRunner = "com.practice.testarchitecture.util.MainTestRunner"
}

 

 

class MainCoroutineRule(
    private val testDispatcher: TestDispatcher = UnconfinedTestDispatcher()
) : TestWatcher() {

    override fun starting(description: Description) {
        super.starting(description)
        Dispatchers.setMain(testDispatcher)
    }

    override fun finished(description: Description) {
        super.finished(description)
        Dispatchers.resetMain()
    }
}

테스트 코루틴을 사용하기 위해서 코루틴 관련 rule을 설정해 주면 된다.

 

@HiltAndroidTest
class TestGithubRepository {

    private val coroutineRule = MainCoroutineRule()

    private val hiltRule = HiltAndroidRule(this)

    @get:Rule
    val rule: RuleChain = RuleChain
        .outerRule(hiltRule)
        .around(coroutineRule)


    @Inject
    lateinit var searchRepositoryUseCase: SearchRepositoryUseCase

    @Inject
    lateinit var githubRepository: GithubRepository

    @Before
    fun init() {
        hiltRule.inject()
    }

    @Test
    fun test() {
        runTest {
            println(searchRepositoryUseCase(SearchRepositoryUseCase.Param("123")))
        }
    }
}

dagger2에서는 설정 방법이 좀 더 복잡하였지만 hilt에서는 위와 같이 HiltAndroidRule을 junit의 @Before 어노테이션을 이용하여 설정해 주면 된다. (스프링 junit 사용법과 같다.)

 

위와 같이 작업 후 실행해 주면 아래와 같은 결과를 받아 올 수 있다.

 

코루틴 룰을 사용하지 않고 mockk의 코틀린 전용 라이브리를 사용하여 더미 데이터로도 테스트가 가능하다.

mockk에는 coEvery, coVerify, coMatch, coAssert, coRun, coAnswers or coInvoke 같은 코루틴 suspend함수를 실행할 수 있는 함수 들이 있다.

coEvery를 이용하여 예제를 작성해 보면

@HiltAndroidTest
class TestGithubRepository {

    private val coroutineRule = MainCoroutineRule()

    private val hiltRule = HiltAndroidRule(this)

    @get:Rule
    val rule: RuleChain = RuleChain
        .outerRule(hiltRule)
        .around(coroutineRule)


    @Inject
    lateinit var searchRepositoryUseCase: SearchRepositoryUseCase

    private val searchRepositoryUseCase2 : SearchRepositoryUseCase = mockk()


    @Inject
    lateinit var githubRepository: GithubRepository

    @Before
    fun init() {
        hiltRule.inject()
    }

    @Test
    fun test() {

        coEvery {
            searchRepositoryUseCase2(SearchRepositoryUseCase.Param("123"))
        } returns Result.Success(GitHubRepositoryResponse(items = emptyList(), totalCount = 0))

        runTest {
            println(searchRepositoryUseCase2(SearchRepositoryUseCase.Param("123")))
            println(searchRepositoryUseCase(SearchRepositoryUseCase.Param("123")))
        }
    }
}

 

출력)
System.out: Success(data=GitHubRepositoryResponse(totalCount=0, items=[]))
Success(data=GitHubRepositoryResponse(totalCount=228558, items=[ ....

이와 같이 더미 데이터를 출력할 수 있다.

runTest에서 searchRepositoryUsecase2의 Param("123")이 아닐 경우 설정한 테스트 값이 아니므로 오류가 발생한다.

 

자세한 사용)

https://mockk.io/

 

출처)

https://developer.android.com/training/dependency-injection/hilt-testing?hl=ko 

https://github.com/android/sunflower/blob/4df9e411ce3946ed92349da2a9061b42d1d7ddfc/app/src/androidTest/java/com/google/samples/apps/sunflower/MainCoroutineRule.kt

반응형