[英]Let suspend function not return anything
考慮這個類:
class TestViewModel(private val interactor: LoginInteractor) : ViewModel() {
private val _loading = MutableLiveData<Boolean>().apply { value = false }
val loading: LiveData<Boolean> = _loading
fun loginClicked() {
viewModelScope.launch {
_loading.value = true
val isLoggedIn = interactor.login()
_loading.value = false
}
}
}
interface LoginInteractor {
suspend fun login(): Boolean
}
和測試:
class TestViewModelTest {
@Rule
@JvmField
var rule = InstantTaskExecutorRule()
@Mock
private lateinit var interactor: LoginInteractor
@InjectMocks
private lateinit var tested: TestViewModel
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
Dispatchers.setMain(TestCoroutineDispatcher())
}
@Test
fun `should set loading to true while loading`() = runBlockingTest {
given(interactor.login()).willReturn(true)
tested.loginClicked()
Assert.assertTrue(tested.loading.value!!)
}
}
當斷言loading
值為true
,顯然它實際上不是。
當我們使用 RxJava 時, LoginInteractor
看起來像:
interface LoginInteractor {
fun login(): Single<Boolean>
}
在測試中,我們可以做到
given(interactor.login()).willReturn(Single.never())
測試登錄時ViewModel的狀態; 當loginClicked()
被調用但interactor.login()
尚未返回時,如何延遲/不返回交互器的任何suspend
函數login()
以測試ViewModel 的狀態?
選項1:
為了保證你的狀態發生變化,你可以訂閱加載狀態的變化:
@Test
fun `should set loading to true while loading`() = runBlockingTest {
given(interactor.login()).willReturn(true)
var invocationCounter = 0
tested.loading.observerForever { loading ->
assertEquals(invocationCounter == 0, loading)
invocationCounter++
}
tested.loginClicked()
Assert.assertTrue(tested.loading.value!!)
}
選項 2:
```
given(interactor.login()).willAnswer {
assertTrue(tested.loading.value)
true
}
tested.loginClicked()
Assert.assertFalse(tested.loading.value!!)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.