web-dev-qa-db-ja.com

ユニットテスト新しいKotlin Coroutine Stateflow.

最近最近でした 紹介された コトリンコルーチンの一部としてクラスStateFlow

私は現在それを試して、私のViewModelをテストしようとしている間に問題を見つめています。私が達成したいのです:私のStateFlowが私のViewModelの正しい順序ですべての状態値を受け取っていることをテストします。

私のコードは以下の通りです:

ビューモーデル:

_class WalletViewModel(private val getUserWallets: GetUersWallets) : ViewModel() {

val userWallet: StateFlow<State<UserWallets>> get() = _userWallets
private val _userWallets: MutableStateFlow<State<UserWallets>> =
    MutableStateFlow(State.Init)

fun getUserWallets() {
    viewModelScope.launch {
        getUserWallets.getUserWallets()
            .onStart { _userWallets.value = State.Loading }
            .collect { _userWallets.value = it }
    }
}
_

私のテスト:

_    @Test
fun `observe user wallets ok`() = runBlockingTest {
    Mockito.`when`(api.getAssetWallets()).thenReturn(TestUtils.getAssetsWalletResponseOk())
    Mockito.`when`(api.getFiatWallets()).thenReturn(TestUtils.getFiatWalletResponseOk())

    viewModel.getUserWallets()

    val res = arrayListOf<State<UserWallets>>()
    viewModel.userWallet.toList(res) //doesn't works

    Assertions.assertThat(viewModel.userWallet.value is State.Success).isTrue() //works, last value enmited
}
_

最後の値にアクセスされた作品にアクセスします。しかし、私がテストしたいのは、すべての放出された値が正しい順序で放出されることです。このコードで:viewModel.userWallet.toList(res) //doesn't works次のエラーが発生しました:

_Java.lang.IllegalStateException: This job has not completed yet
    at kotlinx.coroutines.JobSupport.getCompletionExceptionOrNull(JobSupport.kt:1189)
    at kotlinx.coroutines.test.TestBuildersKt.runBlockingTest(TestBuilders.kt:53)
    at kotlinx.coroutines.test.TestBuildersKt.runBlockingTest$default(TestBuilders.kt:45)
    at WalletViewModelTest.observe user wallets ok(WalletViewModelTest.kt:52)
....
_

私は私が明白なものを逃していると思います。しかし、私がコルーチンとフローを始めるだけで、RunBlockingTestを使用していないときにこのエラーが発生しているようです。

編集:一時的な解決策として、ライブデータとしてテストしています。

_    @Captor
    lateinit var captor: ArgumentCaptor<State<UserWallets>>

    @Mock
    lateinit var walletsObserver: Observer<State<UserWallets>>

    @Test
    fun `observe user wallets ok`() = runBlockingTest {
        viewModel.userWallet.asLiveData().observeForever(walletsObserver)

        viewModel.getUserWallets()

        captor.run {
            Mockito.verify(walletsObserver, Mockito.times(3)).onChanged(capture())
            Assertions.assertThat(allValues[0] is State.Init).isTrue()
            Assertions.assertThat(allValues[1] is State.Loading).isTrue()
            Assertions.assertThat(allValues[2] is State.Success).isTrue()
        }
    }
_
10
agonist_

あなたが直面している問題は、tolist()が完了するフローを必要とし、ドキュメントに従って "State Flowが完了しない"を必要とするからです。

https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-state-flow/

https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/to-list.html

0
atorresveiga