Skip to content Skip to sidebar Skip to footer

How To Inject Viewmodelscope For Android Unit Test With Kotlin Coroutines?

Questions What is the best strategy to inject viewModelScope for Android unit tests with Kotlin coroutines? When the CoroutineScope is injected into a ViewModel for unit tests, sh

Solution 1:

Inject and determine CoroutineScope on ViewModel creation

In production, the ViewModel is created with a null coroutineScopeProvider, as the ViewModel's viewModelScope is used. For testing, TestCoroutineScope is passed as the ViewModel argument.

SomeUtils.kt

/**
 * Configure CoroutineScope injection for production and testing.
 *
 * @receiver ViewModel provides viewModelScope for production
 * @param coroutineScope null for production, injects TestCoroutineScope for unit tests
 * @return CoroutineScope to launch coroutines on
 */fun ViewModel.getViewModelScope(coroutineScope: CoroutineScope?) =
    if (coroutineScope == null) this.viewModelScope
    else coroutineScope

SomeViewModel.kt

classFeedViewModel(
    privateval coroutineScopeProvider: CoroutineScope? = null,
    privateval repository: FeedRepository
) : ViewModel() {

    privateval coroutineScope = getViewModelScope(coroutineScopeProvider)

    fungetSomeData() {
        repository.getSomeDataRequest().onEach {
            // Some code here.            
        }.launchIn(coroutineScope)
    }

}

SomeTest.kt

@ExperimentalCoroutinesApiclassFeedTest : BeforeAllCallback, AfterAllCallback {privateval testDispatcher = TestCoroutineDispatcher()
    privateval testScope = TestCoroutineScope(testDispatcher)
    privateval repository = mockkClass(FeedRepository::class)privatevar loadNetworkIntent = MutableStateFlow<LoadNetworkIntent?>(null)

    overridefunbeforeAll(context: ExtensionContext?) {
        // Set Coroutine Dispatcher.
        Dispatchers.setMain(testDispatcher)
    }

    overridefunafterAll(context: ExtensionContext?) {
        Dispatchers.resetMain()
        // Reset Coroutine Dispatcher and Scope.
        testDispatcher.cleanupTestCoroutines()
        testScope.cleanupTestCoroutines()
    }

    @TestfuntopCafesPoc() = testDispatcher.runBlockingTest {
        ...
        val viewModel = FeedViewModel(testScope, repository)
        viewmodel.getSomeData()
        ...
    }
}

Post a Comment for "How To Inject Viewmodelscope For Android Unit Test With Kotlin Coroutines?"