【问题标题】:Base Presenter Test class using Mockito and Kotlin - working around Generic type erasure使用 Mockito 和 Kotlin 的 Base Presenter Test 类 - 解决通用类型擦除
【发布时间】:2018-08-17 23:44:43
【问题描述】:

我正在尝试使用泛型编写一个基本测试类来减少样板代码。它专门用于测试(MVP)演示者,我正在使用 Mockito 来模拟 View 界面。例如。像这样(简化):

abstract class BasePresenterTest<V: BaseView, P: BasePresenter<V>> {

    @Mock
    lateinit var mockView: V

    lateinit var presenter: P

    @Before
    open fun setUp() {
        MockitoAnnotations.initMocks(this)
    }

    // ...
}

这是一个问题,因为类型擦除意味着 Mockito 无法模拟泛型参数中传递的具体 View 类型。尝试运行此类测试将在运行时生成 java.lang.ClassCastException: BaseView$MockitoMock$1481956224 cannot be cast to ConcreteView

我目前的解决方法是添加一个抽象函数来返回视图类,以便可以直接在基类中模拟它:

abstract class BasePresenterTest<V: BaseView, P: BasePresenter<V>> {

    lateinit var mockView: V

    lateinit var presenter: P

    abstract fun getViewClass(): Class<V>

    @Before
    open fun setUp() {
        mockView = Mockito.mock(getViewClass())
    }

    // ...
}

这意味着具体测试类中有更多样板代码,这在某种程度上完全违背了基础测试类的目的。它也是泛型类型擦除的经典 Java 解决方法。我想知道是否有更好的方法来使用 Kotlin 做到这一点? (我在想以某种方式具体化泛型类型参数,但它们只适用于内联函数。)

【问题讨论】:

    标签: android kotlin mockito


    【解决方案1】:

    在 Kotlin 中想不出更好的方法,但我认为您应该重新考虑您的设计决策,并最终使用组合将您可能想要在不同演示者之间共享的任何代码移动到单独的类中。

    为了仍然保持调用的便利性,您可以让这个公共演示者类成为特定类的委托,如下所示:

    class MyCommonPresenter : CommonPresenter {
        ...
    }
    
    class MySpecificPresenter internal constructor(common: CommonPresenter) 
        : CommonPresenter by common {
        constructor() = this(MyCommonPresenter())
        ...
    }
    

    然后您只需为MyCommonPresenter 编写一个测试并将其视为MySpecificPresenter 测试的可模拟依赖项。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-11-23
      • 1970-01-01
      • 1970-01-01
      • 2011-11-04
      • 2020-04-17
      • 2018-01-30
      • 1970-01-01
      相关资源
      最近更新 更多