Написать тестовый блок для ViewModel в kotlin - PullRequest
1 голос
/ 03 октября 2019

Я использую 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 Test class

@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()
    }
}

Проблема в том, что мои жизненные данные обернуты вокруг Event<DataState<List<TrendingResponse>>, из-за чего я не могу получить то, что должно быть dataObserver, и как мне проверить, что dataObserver в тестовом классе.

Событие или открытый класс, который должен обрабатывать событие, подобное SingleLiveData

DataState - это запечатанный класс, который содержит класс данных SUCCESS & FAILED

Я написал жизненные данные тестового примера как LiveData<List<Response> или что-то типа того.

1 Ответ

0 голосов
/ 19 октября 2019

Вам нужно обернуть List<TrendingResponse>Event(DataState.Success(List<TrendingResponse>)), который вы возвращаете, используя mockito - 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)


}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...