ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 코루틴 테스트 환경(runTest vs UnconfinedTestDispatcher) 완벽 이해하기
    kotlin/coroutine 2025. 10. 31. 22:48

    Objective

    Compose 및 ViewModel 테스트에서 적절한 코루틴 테스트 환경을 선택하고, 안정적이고 예측 가능한 테스트를 구현한다.


    Key Results

    KR1. runTest  TestScope + TestDispatcher 의 차이를 명확히 이해한다.

    항목 runTest TestScope + TestDispatcher
    스코프 생성 자동 생성 수동 생성
    시간 제어 가상 시간 (advanceTimeBy 등) 가능 실제 시간 기반
    정리(cleanup) 자동 정리 직접 관리 필요
    DI 주입 제한적 명시적 주입 용이
    권장 사용처 단순 비동기 단위 테스트 ViewModel, Compose, DI 환경

    핵심 요약:

    • runTest → 테스트 코루틴의 표준 진입점, 가상 시간 제어 가능
    • TestScope + TestDispatcher → 유연한 수동 설정, 주로 DI 구조에서 사용

    KR2. UnconfinedTestDispatcher 의 동작 원리를 이해한다.

    • 즉시 실행(immediate): launch 시점에 바로 실행됨
    • 스레드 제약 없음(unconfined): 실행 스레드에 제한이 없음
    • 가상 시간 미지원: delay() 는 실제 시간만큼 기다림 (실제 1초는 진짜 1초 대기)

    즉, 빠른 실행이 장점이지만, 시간 제어가 필요한 테스트에는 부적합하다.


    KR3. Compose/ViewModel 테스트에서 왜 UnconfinedTestDispatcher 를 사용하는지 이유를 이해한다.

    1. 즉시 실행이 필요하다.

    Compose 의 collectAsStateWithLifecycle() 은 상태 변화를 즉시 반영해야 한다.
    StandardTestDispatcher 는 launch 가 지연되어 UI가 갱신되지 않을 수 있다.

    2. ViewModelScope 의 launch 를 바로 실행해야 한다.

    테스트 중 ViewModel 이 내부에서 launch 를 호출하면
    UnconfinedTestDispatcher 덕분에 즉시 수행되어 상태를 바로 검증할 수 있다.

    3. 대부분의 Compose 테스트는 가상 시간 제어가 필요 없다.

    대부분은 상태 변경 검증 위주이며 delay()  timeout() 을 다루지 않는다.


    KR4. 하지만 runTest 가 여전히 필요한 상황을 구분할 수 있다.

    runTest 는 시간 제어가 필요한 테스트에 반드시 필요하다.

    예시:

     
    viewModel.retryAfterDelay() delay(5000)
    • UnconfinedTestDispatcher → 실제 5초 대기
    • runTest  advanceTimeBy(5000) 으로 즉시 가상 시간 이동 가능

    즉, delay, retry, timeout 등의 로직이 포함되면 runTest + StandardTestDispatcher 조합이 필수이다.


    KR5. 상황별 Dispatcher 선택 기준을 명확히 정리한다.

    테스트 유형 권장 Dispatcher 이유
    Compose UI 테스트 UnconfinedTestDispatcher 즉시 실행, UI 상태 반영이 즉각적
    ViewModel 로직 테스트 (delay, retry 등) StandardTestDispatcher + runTest 가상 시간 제어 필요
    Repository / Flow 단위 테스트 runTest 지연, 예외, collect 로직 테스트
    UI + ViewModel 통합 테스트 상황에 따라 혼용 즉시 실행은 Unconfined, 시간 제어는 Standard

    Insight (결론)

    • UnconfinedTestDispatcher 는 Compose 및 ViewModel 테스트에서 즉시 상태 변화 검증을 가능하게 하는 기본 옵션이다.
    • 하지만 시간이 중요한 로직에는 반드시 runTest + StandardTestDispatcher 를 사용해야 한다.
    • “하나는 필수, 다른 하나는 비추천”이 아니라, 테스트 목적에 따라 올바르게 선택하는 것이 중요하다.
Designed by Tistory.