LiveData 테스트 하기

ganghee·2022년 2월 24일
0

Test

목록 보기
3/5
post-thumbnail

LiveData 테스트를 한다면 JUnit4와 JUnit5의 Rule설정을 다르게 해줘야한다.
JUnit4에서는 Rule을 지원하지만 JUnit5에서는 더이상 지원하지 않아 Extension을 만들어 줘야한다.

먼저 JUnit4에서 Rule 설정하는 방법을 알아보자.

  1. build.gradle에 다음과 같은 디펜던시를 추가하자
testImplementation 'androidx.arch.core:core-testing:2.1.0'
  1. 이제 테스트 클래스에 Rule을 추가하자
class CalculatorViewModelTest {
    @get:Rule
    val instantExecutorRule = InstantTaskExecutorRule()
    ...
}

JUnit5에서는 다르게 해줘야한다.

안그러면 다음과 같은 에러가 나온다.

Method getMainLooper in android.os.Looper not mocked. See http://g.co/androidstudio/not-mocked for details.
java.lang.RuntimeException: Method getMainLooper in android.os.Looper not mocked. See http://g.co/androidstudio/not-mocked for details.
  1. 테스트 패키지 안에 다음과 같은 클래스를 추가하자.
class InstantTaskExecutorExtension : BeforeEachCallback, AfterEachCallback {
    override fun beforeEach(context: ExtensionContext?) {
        ArchTaskExecutor.getInstance().setDelegate(object : TaskExecutor() {
            override fun executeOnDiskIO(runnable: Runnable) {
                runnable.run()
            }

            override fun postToMainThread(runnable: Runnable) {
                runnable.run()
            }

            override fun isMainThread(): Boolean {
                return true
            }
        })
    }

    override fun afterEach(context: ExtensionContext?) {
        ArchTaskExecutor.getInstance().setDelegate(null)
    }
}
  1. 테스트 클래스에 1에서 만든 클래스를 지정해주자.
class CalculatorViewModelTest {
    @JvmField
    @RegisterExtension
    val instantTaskExecutorExtension = InstantTaskExecutorExtension()

LiveData 테스트 함수 만들기

  1. 라이브 데이터를 테스트하기 위해서는 다음과 같은 확장 함수를 추가해야 합니다.
fun <T> LiveData<T>.getOrAwaitValue(
    time: Long = 2,
    timeUnit: TimeUnit = TimeUnit.SECONDS
): T {
    var data: T? = null
    val latch = CountDownLatch(1)
    val observer = object : Observer<T> {
        override fun onChanged(o: T?) {
            data = o
            latch.countDown()
            this@getOrAwaitValue.removeObserver(this)
        }
    }

    this.observeForever(observer)

    // 2초 동안 liveData가 바뀌지 않는다면 에러를 반환
    // 무한 대기를 방지하고 다음 liveData 테스트를 빠르게 진행하기 위함
    if (!latch.await(time, timeUnit)) {
        throw TimeoutException("LiveData value was never set.")
    }

    @Suppress("UNCHECKED_CAST")
    return data as T
}

위의 코드는 LiveData는 2초 동안 값이 바뀌지 않는 경우 에러가 나오도록 구현되었습니다.
라이브 데이터는 Obserbe 패턴을 가지고 있기 때문에 비동기를 구현할 수 있습니다. 하지만 데이터가 변경되기까지 하염없이 기다릴 수는 없습니다. 그래서 위와 같은 확장함수를 구현해야 합니다.

  1. 테스트 함수는 다음과 같이 구현할 수 있습니다. 계산기 프로젝트에 적용하면 다음과 같습니다.
@Test
    fun `수식 1 을 입력하면 1이 보여야한다`() {
        // WHEN
        calculatorViewModel.appendOperand(1)

        // THEN
        assertThat(calculatorViewModel.statement.getOrAwaitValue()).isEqualTo("1")
    }

0개의 댓글