如何测试演示者 MVP 安卓



我试图了解如何测试我的应用程序,我还在学习mockito我也看到了mockk但无法使其工作,这是我Presenter

class MyPresenterImpl @Inject constructor(var myUseCase: MyUseCase) : MyContract.Presenter {
private var mView: MyContract.View? = null
private var disposable: Disposable? = null

override fun attachView(view: MyContract.View) {
this.mView = view
this.mView?.showProgressBar(true)
}
override fun loadResults() {
disposable = getList.execute()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ result ->
mView?.showProgressBar(false)
mView?.showResults(result)
},
{ error ->
mView?.showProgressBar(false)
mView?.showError(error.localizedMessage)
})
}
override fun rxJavaUnsuscribe() {
if (disposable != null && !disposable!!.isDisposed) {
disposable!!.dispose()
}
}
override fun detachView() {
this.mView = null
}
}

我应该如何测试这个演示者?我必须添加所有这些方法吗?

我试图用mockito做到这一点,但我也可以使用mockk.

有些人告诉我,我必须对Schedulers做一些事情并使用trampoline,但我不清楚你们中的任何人都可以提供一个例子或解释一下吗?

如果我正确理解了你的问题,那么你正在尝试了解如何通过单元测试(使用 Mockito)实现完整的 MVP 模式。

我写了一个示例代码(显示书籍列表的应用程序),它解释了一个基本的 MVP 实现,其中包含一个 JUnit 测试用例: https://github.com/harneev/AndroidMVPkt

让我们在这里谈谈类:

  1. ViewContract.kt- 接口定义方法,用于指导哑视图执行操作。
  2. ModelContract.kt- 定义获取数据(从数据库或服务器)的方法的接口,这些数据将封装在实现类下。
  3. Presenter.kt- 处理所有业务逻辑,并通过作为参数注入的具体视图和模型来编排此逻辑。

注意:表示器是常规类和业务逻辑业务流程协调程序,取决于模型和视图。一些开发人员喜欢PresenterView接口添加引用,但这种方式更干净。

现在来看这个MVP设计的单元测试用例(PresenterTest.kt)。

我正在使用 mockito-kotlin 作为更好的 kotlin 的模拟框架 支持。

在这种情况下,我只添加了一个名为test if books are displayed() 的测试用例,它模拟ViewContractModelContract并初始化Presenter。最后Mockito.verify该方法验证视图是否收到了模型生成的书籍列表。

为了更好的单元测试用例,我总是将其分解为以下三种情况,解释如下:

// 1. given
how mocks will behave when their respective methods are called
// 2. when
when execution method is called
// 3. then
verify / assert if required action is performed

希望这有帮助。

  1. 为测试包中的 junit 测试创建自定义规则TestSchedulerRule.kt

    class TestSchedulerRule(private val scheduler: Scheduler = Schedulers.trampoline()) : TestRule {
    override fun apply(base: Statement, d: Description): Statement {
    return object : Statement() {
    override fun evaluate() {
    RxJavaPlugins.setIoSchedulerHandler { scheduler }
    RxJavaPlugins.setComputationSchedulerHandler { scheduler }
    RxJavaPlugins.setNewThreadSchedulerHandler { scheduler }
    RxJavaPlugins.setSingleSchedulerHandler { scheduler }
    RxAndroidPlugins.setInitMainThreadSchedulerHandler { scheduler }
    RxAndroidPlugins.setMainThreadSchedulerHandler { scheduler }
    try {
    base.evaluate()
    } finally {
    RxJavaPlugins.reset()
    RxAndroidPlugins.reset()
    }
    }
    } 
    }
    }
    
  2. 为演示者创建MyPresenterImplTest,并使用创建的规则编写所需的单元测试。例如,我使用kotlin-mockitojunit4为演示者逻辑添加了一个测试。

    @RunWith(MockitoJUnitRunner::class)
    class MyPresenterImplTest {
    @Rule
    @JvmField
    val testRule = TestSchedulerRule()
    private val view: MyContract.View = mock()
    private val myUseCase: MyUseCase = mock()
    private val presenter = MyPresenterImpl(myUseCase)
    @Before
    fun setUp() {
    presenter.attachView(view)
    }
    @Test
    fun `WHEN btnLoad clicked EXPECT load and show results`() {
    //create needed results
    val results = listOf<Any>()
    //mock the result of execution myUseCase.invoke()
    whenever(myUseCase.invoke()).thenReturn(Single.just(results))
    //trigger the needed action
    presenter.loadResults()
    //verify that all needed actions were called
    verify(myUseCase).invoke()
    verify(view).showResults(results)
    }
    }
    

关于规则的说明。

我们需要创建自定义测试规则,因为 AndroidSchedulers.mainThread() 返回的默认调度程序(当您在演示器中编写 .observeOn(AndroidSchedulers.mainThread() 时)是 LooperScheduler的一个实例,并且依赖于 JUnit测试中不可用的 Android 依赖项。

因此,我们需要在测试运行之前使用不同的调度程序初始化RxAndroid插件。使用规则允许您跨多个测试类重用初始化逻辑。

若要为演示者编写单元测试,应: 1. 模拟myUseCaseprivate val myUseCase = mock<MyUseCase>() 2. addSchedulers.io()andAndroidSchedulers.mainThread()to the constructor of the presenter then you can setSchedulers.trampoline()' 当您创建用于测试的演示器对象时:

class MyPresenterImpl @Inject constructor(
val myUseCase: MyUseCase,
val ioScheduler: Scheduler = Schedulers,
val uiScheduler: Scheduler = AndroidSchedulers.mainThread()
) : MyContract.Presenter

然后在测试seUp()

presenter = MyPresenterImpl(myUseCase, Schedulers.trampoline(), Schedulers.trampoline())
  1. 存根用例的函数execute()
myUseCase.stub {
on { execute() }.thenReturn(Single.just(xyz))
}
  1. 验证您的代码

注意:我更喜欢使用Mockito版本的Nhaarman。

相关内容

  • 没有找到相关文章

最新更新