运行多个测试(Kotlin)时,只有第一个测试通过TestScheduler,

我试图在Kotlin中使用RxJava在MVP体系结构中测试我的演示者。 我已经创建了一个测试规则,用TestScheduler替换通常的调度程序来测试异步请求:

 class TestSchedulerRule : TestRule { val testScheduler = TestScheduler() override fun apply(base: Statement, d: Description): Statement { return object : Statement() { @Throws(Throwable::class) override fun evaluate() { RxJavaPlugins.setInitIoSchedulerHandler { testScheduler } RxJavaPlugins.setInitComputationSchedulerHandler { testScheduler } RxJavaPlugins.setInitNewThreadSchedulerHandler { testScheduler } RxJavaPlugins.setInitSingleSchedulerHandler { testScheduler } RxAndroidPlugins.setInitMainThreadSchedulerHandler { testScheduler } try { base.evaluate() } finally { RxJavaPlugins.reset() RxAndroidPlugins.reset() } } } } } 

这是我的测试课。 问题是每个测试都是通过的,如果我分别运行它们,但是如果我运行整个套件,只有第一个测试通过。 TestScheduler应该有一个问题,因为如果我使用立即的调度程序,它会起作用。

 class UserListPresenterTest { @Rule @JvmField val testSchedulerRule = TestSchedulerRule() @Mock lateinit var mockGetUsers: GetUsers @Mock lateinit var mockView: UserListView lateinit var userListPresenter: UserListPresenter @Before fun setup() { MockitoAnnotations.initMocks(this) userListPresenter = UserListPresenter(mockGetUsers) } @Test fun testGetUsers_errorCase_showError() { // Given val error = "Test error" val single: Single<List> = Single.create { emitter -> emitter?.onError(Exception(error)) } // When `when`(mockGetUsers.execute(Mockito.anyInt(), Mockito.anyBoolean())).thenReturn(single) userListPresenter.attachView(mockView) userListPresenter.getUsers() testSchedulerRule.testScheduler.triggerActions() // Then verify(mockView).hideLoading() verify(mockView).showError() } @Test fun testGetUsers_successCaseFirstPage_clearList() { // Given val users = listOf(UserViewModel(1, "Name", 1000, "")) val single: Single<List> = Single.create { emitter -> emitter?.onSuccess(users) } // When `when`(mockGetUsers.execute(Mockito.anyInt(), Mockito.anyBoolean())).thenReturn(single) userListPresenter.attachView(mockView) userListPresenter.getUsers() testSchedulerRule.testScheduler.triggerActions() // Then verify(mockView).clearList() } } 

这是我在控制台中得到的错误:

 Wanted but not invoked: mockView.hideLoading(); -> at com.example.tamaskozmer.kotlinrxexample.UserListPresenterTest.testGetUsers_errorCase_showError(UserListPresenterTest.kt:57) Actually, there were zero interactions with this mock. at com.example.tamaskozmer.kotlinrxexample.UserListPresenterTest.testGetUsers_errorCase_showError(UserListPresenterTest.kt:57) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) at com.example.tamaskozmer.kotlinrxexample.TestSchedulerRule$apply$1.evaluate(TestSchedulerRule.kt:28) at org.junit.rules.RunRules.evaluate(RunRules.java:20) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.intellij.rt.execution.application.AppMainV2.main(AppMainV2.java:131) 

UserListPresenter类

 class UserListPresenter(private val getUsers: GetUsers) : BasePresenter() { private val offset = 5 private var page = 1 private var loading = false fun getUsers(forced: Boolean = false) { loading = true if (forced) { resetPaging() } getUsers.execute(page, forced) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe({ users -> loading = false if (page == 1) { view?.clearList() } view?.addUsersToList(users) view?.hideLoading() page++ }, { loading = false view?.showError() view?.hideLoading() }) } private fun resetPaging() { page = 1 } fun onScrollChanged(lastVisibleItemPosition: Int, totalItemCount: Int) { if (!loading) { if (lastVisibleItemPosition >= totalItemCount - offset) { getUsers() } } if (loading && lastVisibleItemPosition >= totalItemCount) { view?.showLoading() } } } 

刚解决同样的问题。 您应该定义您的调度程序,而不是在规则中指定它们。 RxAndroidPlugins将保留TestScheduler的第一个实例后TestRule.apply将把另一个实例新的测试。

将设置调度程序处理程序放在随附对象中将会有所帮助

 companion object { val testScheduler: TestScheduler init { testScheduler = TestScheduler() RxAndroidPlugins.setInitMainThreadSchedulerHandler { _ -> testScheduler } RxJavaPlugins.setInitComputationSchedulerHandler { _ -> testScheduler } RxJavaPlugins.setInitIoSchedulerHandler { _ -> testScheduler } } }