如何测试主持人MVP Android

时间:2019-05-09 15:37:49

标签: android unit-testing kotlin mockito mockk

我试图了解如何测试我的应用,我仍在学习sbt,我也看到了mockito,但无法正常运行,这是我的{{1} }

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,但是对我来说尚不清楚有人可以提供示例还是对它进行一些解释?< / p>

3 个答案:

答案 0 :(得分:0)

要为演示者编写单元测试,您应该:  1.模拟myUseCaseprivate val myUseCase = mock<MyUseCase>() 2. add Schedulers.io()and AndroidSchedulers.mainThread()to the constructor of the presenter then you can set Schedulers.trampoline()`在创建演示者对象进行测试时:< / p>

    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. 验证您的代码

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

答案 1 :(得分:0)

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

我编写了一个示例代码(该应用程序显示书籍列表),在这里说明了一个JUnit测试用例的基本MVP实现:https://github.com/harneev/AndroidMVPkt

让我们在这里谈谈课程:

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

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

现在要使用此 MVP 设计的单元测试用例(PresenterTest.kt)。

  

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

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

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

// 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

希望这会有所帮助。

答案 2 :(得分:0)

  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-mockito junit4 为演示者逻辑添加了一项测试。

    @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依赖项

因此,我们需要在测试运行之前使用其他Scheduler初始化RxAndroidPlugins。使用规则可让您在多个测试类之间重用初始化逻辑。