Rxjava 2 при ошибке не вызывается во время модульного тестирования - PullRequest
0 голосов
/ 13 марта 2019

Rxjava 2 при ошибке не вызывается во время модульного тестирования.Я использую kotlin с rxJava 2.

метод

  @SuppressLint("CheckResult")
    override fun fetchFilms() {
        view.showLoader(true)
        disposable = getRetrofitInstance(false).create(API::class.java)
                .fetchFilms()
                .subscribeOn(io)
                .observeOn(main)
                .subscribeWith(object : DisposableObserver<Response>() {
                    override fun onComplete() {
                    }

                    override fun onNext(t: Response) {
                        println(t)
                        view.setAdapter(t?.results as List<ResultsItem>)
                        view.showLoader(false)
                    }

                    override fun onError(e: Throwable) {
                        e.printStackTrace()
                        view.showLoader(false)
                        view.showError(e.message.toString())                    }

                })


    }

Тест

@Test
    fun  fetchInvalidDataShouldThrowError(){

        `when`(api.fetchFilms()).thenReturn(Observable.error(IOException()))
   filmsPresenter.fetchFilms()
        val subscriber = TestSubscriber<Response>()

        subscriber.awaitTerminalEvent(5,TimeUnit.SECONDS)

        verify(filmsView, times(1)).showLoader(true)
        verify(filmsView).showError("t")
        verify(filmsView).showLoader(false)


    }

Ответы [ 3 ]

1 голос
/ 13 марта 2019

Похоже, вы выполняете свой код асинхронно и в тестах.

Вы должны синхронизировать используемые ранее планировщики.

@Before
fun setupSchedulers() {
    RxAndroidPlugins.setMainThreadSchedulerHandler { Schedulers.trampoline() }
    RxJavaPlugins.setIoSchedulerHandler { Schedulers.trampoline() }
}

@Test
fun  fetchInvalidDataShouldThrowError() {
    `when`(api.fetchFilms()).thenReturn(Observable.error(IOException("t")))
    filmsPresenter.fetchFilms()

    verify(filmsView).showLoader(true)
    verify(filmsView).showError("t")
    verify(filmsView).showLoader(false)
}
0 голосов
/ 14 марта 2019

Я передал репо в Presenter, чтобы иметь тот же экземпляр API.

Вот некоторые изменения, которые я должен сделать

class RepoTest(val api : API) {
    fun filmm() : Observable<Response> {
        return api.fetchFilms()
    }
}

Presenter

class FlimsPresenter(private val view: GetFlimsContract.View,  repo: RepoTest) : GetFlimsContract.Presenter

метод

 override fun fetchFilms() {
        view.showLoader(true)
        disposable = repot.filmm()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeWith(object : DisposableObserver<Response>() {
                    override fun onComplete() {
                    }

                    override fun onNext(t: Response) {
                        println(t)
                        view.setAdapter(t?.results as List<ResultsItem>)
                        if (t?.results.isEmpty()) view.showEmptyView(true)
                        else view.showEmptyView(false)
                        view.showLoader(false)
                    }

                    override fun onError(e: Throwable) {
                        e.printStackTrace()
                        view.showLoader(false)
                        view.showError(e.message.toString())
                    }

                })


    }

Наконец тест

class TestSample {
    @Mock
    private lateinit var filmsPresenter: GetFlimsContract.Presenter


    @Mock
    private lateinit var filmsView: GetFlimsContract.View


    private lateinit var api: API
    @Mock
    private lateinit var disposable: Disposable
    @Mock
    lateinit var repoTest: RepoTest

    @Before
    fun setup() {
        RxAndroidPlugins.setMainThreadSchedulerHandler { scheduler -> Schedulers.trampoline() }
        RxAndroidPlugins.setInitMainThreadSchedulerHandler { scheduler -> Schedulers.trampoline() }
        RxJavaPlugins.setIoSchedulerHandler { t -> Schedulers.trampoline() }
        MockitoAnnotations.initMocks(this)

        repoTest = Mockito.mock(RepoTest::class.java)

        filmsView = Mockito.mock(GetFlimsContract.View ::class.java)

        filmsPresenter = FlimsPresenter(filmsView,repoTest )
    }


    @Test
    fun `should lod item into views`() {

        Mockito.`when`(repoTest.filmm()).thenReturn(Observable.just(Response("","",7, listOf(ResultsItem()))))
        filmsPresenter.fetchFilms()

        Mockito.verify(filmsView).showLoader(true)
        Mockito.verify(filmsView).setAdapter(anyList())
        Mockito.verify(filmsView).showLoader(false)
    }


    @Test
    fun `should show error if network call fails`(){

        Mockito.`when`(repoTest.filmm()).thenReturn(Observable.error(Exception("t")))
        filmsPresenter.fetchFilms()
        Mockito.verify(filmsView).showLoader(true)
        Mockito.verify(filmsView).showError("t")
        Mockito.verify(filmsView).showLoader(false)
    }
}
0 голосов
/ 13 марта 2019

вы на самом деле создаете два API здесь.

каждый раз, когда fetchFilms() на докладчике вызывается, создается новый API. Вы не можете издеваться над API таким образом.

Лучшее предположение, чтобы исправить это - передать объект API в качестве параметра метода в fetchFilms() в презентаторе. таким образом, вы можете решить предоставить настоящий API или фиктивный

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