我正在尝试编写一个带有泛型的基本测试类以减少样板代码。它专门用于测试(MVP(演示者,我正在使用Mockito来模拟视图界面。例如,像这样的东西(简化(:
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 无法模拟在泛型参数中传递的具体视图类型。尝试运行此类测试将在运行时生成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 执行此操作?(我在想以某种方式化泛型类型参数,但它们仅适用于内联函数。
在 Kotlin 中想不出更好的方法,但我认为你应该重新考虑你的设计决策,并最终使用组合将你可能想要在不同演示者之间共享的任何代码移动到一个单独的类中。
为了仍然保持呼叫的便利性,您可以将此公共演示器类设置为特定类的委托,如下所示:
class MyCommonPresenter : CommonPresenter {
...
}
class MySpecificPresenter internal constructor(common: CommonPresenter)
: CommonPresenter by common {
constructor() = this(MyCommonPresenter())
...
}
然后,您只需为MyCommonPresenter
编写一个测试,并将其视为MySpecificPresenter
测试的可模拟依赖项。