Unit Test for a ViewModel class with lazy loading

女生的网名这么多〃 提交于 2021-01-28 04:58:33

问题


I am trying to write a unit test for my viewModel class which has lazy loading. I have following ViewModel class :

abstract class DetailViewModel(item: TmdbItem) : BaseViewModel() {

    private val _trailers = MutableLiveData<List<Video>>()
    val trailers: LiveData<List<Video>>
        get() = _trailers

    private val _cast: MutableLiveData<List<Cast>> by lazy {
        MutableLiveData<List<Cast>>().also {
            arrayOf(composeObservable { getTrailers(item.id) }
                    .subscribe({ videos ->
                        _trailers.postValue(videos)
                    }) { throwable -> Timber.e(throwable) }
                    , composeObservable { getCast(item.id) }
                    .subscribe({ cast ->
                        _cast.postValue(cast)
                    }) { throwable -> Timber.e(throwable) }).also { compositeDisposable.addAll(*it) }
        }
    }
    val cast: LiveData<List<Cast>>
        get() = _cast

    protected abstract fun getTrailers(id: Int): Observable<List<Video>>

    protected abstract fun getCast(id: Int): Observable<List<Cast>>
}

I wrote a unit test for it as follow:

RunWith(MockitoJUnitRunner::class)
class DetailViewModelTest {

    @get:Rule
    var rule: TestRule = InstantTaskExecutorRule()

    @Mock
    private lateinit var api: TmdbApi

    @Test
    fun loadTrailersAndCast() {
        val observableResponseVideo = Observable.just(TmdbApi.VideoWrapper(
                listOf(Video("id", "name", "site", "key", 20, "type"))))
        `when`(api.movieTrailers(1)).thenReturn(observableResponseVideo)

        val observableResponseCast = Observable.just(TmdbApi.CastWrapper(
                listOf(Cast("char", "name", null, 1))))
        `when`(api.movieCast(1)).thenReturn(observableResponseCast)

        val viewModel = MovieDetailViewModel(api, Movie(1, "overview", "2012", null,
                null, "title", 9.0))

        val observer = LoggingObserver<List<Cast>>()
        viewModel.cast.observeForever(observer)

        val observer2 = LoggingObserver<List<Video>>()
        viewModel.trailers.observeForever(observer2)

        with(observer.value) {
            assertThat(this, `is`(notNullValue()))
            assertTrue(this!!.isNotEmpty())
            assertThat(this.size, `is`(1))
        }

        with(observer2.value) {
            assertThat(this, `is`(notNullValue()))
            assertTrue(this!!.isNotEmpty())
            assertThat(this.size, `is`(1))
        }
    }

    /**
     * simple observer that logs the latest value it receives
     */
    private class LoggingObserver<T> : Observer<T> {
        var value: T? = null
        override fun onChanged(t: T?) {
            this.value = t
        }
    }
}

I receive following error when I execute the test:

*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at JPLISAgent.c line: 844



java.lang.StackOverflowError
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:362)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:411)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at io.reactivex.Observable.subscribe(Observable.java:12034)
    at io.reactivex.Observable.subscribe(Observable.java:12016)
    at io.reactivex.Observable.subscribe(Observable.java:11945)
    at com.sample.android.tmdb.ui.detail.DetailViewModel$_cast$2.invoke(DetailViewModel.kt:25)
    at com.sample.android.tmdb.ui.detail.DetailViewModel$_cast$2.invoke(DetailViewModel.kt:12)
    at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
    at com.sample.android.tmdb.ui.detail.DetailViewModel.get_cast(DetailViewModel.kt)
    at com.sample.android.tmdb.ui.detail.DetailViewModel.access$get_cast$p(DetailViewModel.kt:12)
    at com.sample.android.tmdb.ui.detail.DetailViewModel$_cast$2$$special$$inlined$also$lambda$4.accept(DetailViewModel.kt:26)
    at com.sample.android.tmdb.ui.detail.DetailViewModel$_cast$2$$special$$inlined$also$lambda$4.accept(DetailViewModel.kt:12)

Do you know how can I resolve the error?

You can find full source code at : https://github.com/Ali-Rezaei/TMDb-Paging

来源:https://stackoverflow.com/questions/60668360/unit-test-for-a-viewmodel-class-with-lazy-loading

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!