我正在使用Junit&Mockito 4对viewModel进行单元测试。

ViewModel类

class MainViewModel(app: Application, private val githubRepo: GithubRepository) :
    BaseViewModel(app) {


    private val _trendingLiveData by lazy { MutableLiveData<Event<DataState<List<TrendingResponse>>>>() }
    val trendingLiveData: LiveData<Event<DataState<List<TrendingResponse>>>> by lazy { _trendingLiveData }

    var loadingState = MutableLiveData<Boolean>()


    fun getTrendingData(language: String?, since: String?) {
        launch {
            loadingState.postValue(true)
            when (val result = githubRepo.getTrendingListAsync(language, since).awaitAndGet()) {
                is Result.Success -> {
                    loadingState.postValue(false)
                    result.body?.let {
                        Event(DataState.Success(it))
                    }.run(_trendingLiveData::postValue)
                }

                is Result.Failure -> {
                    loadingState.postValue(false)
                }
            }
        }
    }

}


Api EndPoinit

interface GithubRepository {

    fun getTrendingListAsync(
        language: String?,
        since: String?
    ): Deferred<Response<List<TrendingResponse>>>
}


ViewModel测试类

@RunWith(JUnit4::class)
class MainViewModelTest {

    @Rule
    @JvmField
    val instantTaskExecutorRule = InstantTaskExecutorRule()

    @Mock
    lateinit var repo: GithubRepository

    @Mock
    lateinit var githubApi: GithubApi

    @Mock
    lateinit var application: TrendingApp
    lateinit var viewModel: MainViewModel

    @Mock
    lateinit var dataObserver: Observer<Event<DataState<List<TrendingResponse>>>>

    @Mock
    lateinit var loadingObserver: Observer<Boolean>

    private val threadContext = newSingleThreadContext("UI thread")
    private val trendingList : List<TrendingResponse> = listOf()


    @Before
    fun setUp() {
        MockitoAnnotations.initMocks(this)
        Dispatchers.setMain(threadContext)
        viewModel = MainViewModel(application, repo)
    }


    @Test
    fun test_TrendingRepo_whenSuccess() {

        //Assemble
        Mockito.`when`(githubApi.getTrendingListAsync("java", "daily"))
            .thenAnswer{ return@thenAnswer trendingList.toDeferred() }

        //Act
        viewModel.trendingLiveData.observeForever(dataObserver)
        viewModel.loadingState.observeForever(loadingObserver)
        viewModel.getTrendingData("java", "daily")

        Thread.sleep(1000)

        //Verify
        verify(loadingObserver).onChanged(true)
        //verify(dataObserver).onChanged(trendingList)
        verify(loadingObserver).onChanged(false)


    }


    @After
    fun tearDown() {
        Dispatchers.resetMain()
        threadContext.close()
    }
}


问题是我的livedata包裹在Event<DataState<List<TrendingResponse>>周围,由于该原因,我无法获取应为dataObserver的内容以及如何验证测试类中的dataObserver。

Event OS开放类,用于处理诸如SingleLiveData之类的事件

DataState是包含SUCCESS&FAILED数据类的密封类

我已经写了测试用例livedata就像LiveData<List<Response>之类的。

最佳答案

您需要使用mockito-List<TrendingResponse>包装要返回的Event(DataState.Success(List<TrendingResponse>))trendingList.toDeferred()

@Test
fun test_TrendingRepo_whenSuccess() {

    //Assemble
    Mockito.`when`(githubApi.getTrendingListAsync("java", "daily"))
        .thenAnswer{ return@thenAnswer trendingList.toDeferred() }

    //Act
    viewModel.trendingLiveData.observeForever(dataObserver)
    viewModel.loadingState.observeForever(loadingObserver)
    viewModel.getTrendingData("java", "daily")

    Thread.sleep(1000)

    //Verify
    verify(loadingObserver).onChanged(true)
    //wrap the trendingList inside Event(DataState(YourList))
    verify(dataObserver).onChanged(Event(DataState.Success(trendingList)))
    verify(loadingObserver).onChanged(false)


}

10-05 22:38
查看更多