3

我正在使用 Junit & Mockito 4 对 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 端点

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 is likeLiveData<List<Response>或类似的东西。

4

1 回答 1

0

您需要使用 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)


}
于 2019-10-19T17:37:06.077 回答