让挂起功能不 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!!)