【问题标题】:Can`t get response from RxJava in Unit test在单元测试中无法从 RxJava 获得响应
【发布时间】:2021-01-03 05:07:11
【问题描述】:

我试图在单元测试中从 RxJava2 获得响应,我找到了一个示例如何做到这一点,但我看不到和响应,你能帮我吗?谢谢你。 代码本身已经工作了很长时间,没有问题,而当需要测试时我遇到了问题,类似的例子或多或少都是一样的,但是到处都是这样,但它对我不起作用。

演示者那里有我的代码:

  fun register(
    email: String,
    password: String,
    termsEnabled: Boolean,
    dayOfBirth: Int,
    monthOfBirth: Int,
    yearOfBirth: Int,
    formattedBirthDate: String,
    state: String?
) {
    addDisposable(
        registerUseCase.run(
            RegisterUseCase.RegisterRequest(
                email,
                password,
                termsEnabled,
                formattedBirthDate,
                state ?: ""
            )
        )
            .observeOn(mainThreadScheduler)
            .subscribeOn(backgroundScheduler)
            .subscribe(
                { 
                  getView?.showEmptyPassword()
                }, {
                 getView?.showEmptyPassword()
                    }
            )
    )
}

然后测试:

@Before
fun setUp() {
    RxAndroidPlugins.setInitMainThreadSchedulerHandler { 
    Schedulers.trampoline() }
    MockitoAnnotations.initMocks(this)

    
    presenter = CreateAccountPresenter(
        mainThreadScheduler,
        backgroundScheduler,
        registerUseCase,
        getUserDataUseCase,
        getStatesUseCase,
        regexUtils,
        router,
        resourceUtils,
        deviceSharedPreferences
    )
    presenter.setView(view)
}


@Test
fun testRegister() {

    given(registerUseCase.run(RegisterUseCase.RegisterRequest(
        EMAIL, PASSWORD, true,
                FORMATTED_BIRTHDAY, STATE))
    ).willReturn(Single.just(RegisterResponse(false, "ok", "id")))

    presenter.register(
        EMAIL,
        PASSWORD,
        true,
        1,
        1,
        1,
        FORMATTED_BIRTHDAY,
        STATE)

    verify(view).showEmptyPassword()
}

但问题是:

Wanted but not invoked:
view.showEmptyPassword();
-> at 
com.unikrn.esports.umode.CreateAccountPresenterTest.testRegister(CreateAccountPresenterTest.kt:179)
Actually, there were zero interactions with this mock.

【问题讨论】:

  • 你能包含为测试创建演示者的代码吗?我敢打赌,您在后台威胁中运行所有内容。虽然它适用于应用程序,但它不适用于测试(需要阻止)
  • 是的,我试图在代码和测试中设置延迟,没有任何帮助
  • @Pelocho 我认为你是对的,但如何解决?)

标签: android unit-testing mockito rx-java rx-java2


【解决方案1】:

问题是您正在后台线程中进行一些计算,即使被模拟,它也没有足够的时间在 verify 调用之前完成

由于您已经为您的操作注入调度程序,请指定它们都是trampoline,以便所有内容都在同一个线程中运行

@Before
fun setUp() {
    presenter = CreateAccountPresenter(
        Schedulers.trampoline(),
        Schedulers.trampoline(),
        ...
    )
}

在最坏的情况下,您可以添加一些阻止测试执行的阻止程序元素(例如 Semaphore),然后在您的 view 方法之一中释放它(您需要存根)

根据文档,Schedulers.trampoline() 在当前线程中安排所有任务,因此一切都会阻塞。如果您想直接使用像 Schedulers.io() 这样的调度程序,您需要以与现在类似的方式覆盖它们

RxAndroidPlugins.setInitMainThreadSchedulerHandler { Schedulers.trampoline() } // Override MainThreadScheduler

请注意,前面的 sn-p 只是一个示例,您需要对其进行调整

【讨论】:

  • 是的,它有效,谢谢,但你能解释一下原因吗? Schedulers.trampoline() 做什么?
  • 如果我只使用 .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) 它不会工作吗?为什么?
  • 由于您已经在代码中使用它,我假设您知道它是什么以及它是如何工作的。我会在答案中添加一些解释
  • 它创建了那个项目的老开发者,我可以使用它,但我不知道他为什么这样做,这就是我回答的原因
  • 我建议你看一下reactivex.io的官方文档。否则,您将面临几个问题,而这些问题可以通过不犯一些愚蠢的错误来轻松避免
猜你喜欢
  • 1970-01-01
  • 2016-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-26
相关资源
最近更新 更多