让挂起功能不 return 任何东西
Let suspend function not return anything
考虑这个 class:
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()
被调用时,我如何延迟/不 return 我的交互器的 suspend
函数 login()
的任何内容来测试 ViewModel 的状态,但是 interactor.login()
没有return读完了吗?
选项 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!!)
考虑这个 class:
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()
被调用时,我如何延迟/不 return 我的交互器的 suspend
函数 login()
的任何内容来测试 ViewModel 的状态,但是 interactor.login()
没有return读完了吗?
选项 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!!)