【问题标题】:Mockito when clause not working in kotlinMockito when 子句在 kotlin 中不起作用
【发布时间】:2019-01-08 08:36:21
【问题描述】:

我正在尝试在 kotlin 中使用 mockito。我创建了以下测试:

class HeroesDataSourceTest {

    @Mock
    lateinit var heroesRepository: HeroesRepository
    @Mock
    lateinit var params: PageKeyedDataSource.LoadInitialParams<Int>
    @Mock
    lateinit var callback: PageKeyedDataSource.LoadInitialCallback<Int, Heroes.Hero>

    val hero = Heroes.Hero(1, "superman", "holasuperman", 1, null, null)
    val results = Arrays.asList(hero)
    val data = Heroes.Data(results)
    val dataResult = Heroes.DataResult(data)

    val compositeDisposable = CompositeDisposable()

    lateinit var heroesDataSource: HeroesDataSource
    private val heroesPublishSubject = PublishSubject.create<Heroes.DataResult>()

    @Before
    fun initTest(){
        MockitoAnnotations.initMocks(this)

    }

    @Test
    fun testLoadInitialSuccess(){
        `when`(heroesRepository.getHeroes(ArgumentMatchers.anyInt())).thenReturn(heroesPublishSubject.singleOrError())
        heroesDataSource = HeroesDataSource(heroesRepository, compositeDisposable)
        val testObserver = TestObserver<Heroes.DataResult>()
        heroesDataSource.loadInitial(params, callback)
        heroesPublishSubject.onNext(dataResult)
        testObserver.assertComplete()
    }

}

但是当我在when(heroesRepository.getHeroes(ArgumentMatchers.anyInt())).thenReturn(heroesPublishSubject.singleOrError()) 行中执行它时,它只是进入 getHeroes 方法而不是模拟它(并且可以肯定,因为 herosRepository 没有初始化,因为是 mocket 方法失败)。我在java中使用了很多次,它从来没有给我一个问题。我必须在 kotlin 中做什么才能正确模拟它?

编辑

这里我也放了 HeroesRepository 类

open class HeroesRepository {

    val privateKey = "5009bb73066f50f127907511e70f691cd3f2bb2c"
    val publicKey = "51ef4d355f513641b490a80d32503852"
    val apiDataSource = DataModule.create()
    val pageSize = 20

    fun getHeroes(page: Int): Single<Heroes.DataResult> {
        val now = Date().time.toString()
        val hash = generateHash(now + privateKey + publicKey)
        val offset: Int = page * pageSize
        return apiDataSource.getHeroes(now, publicKey, hash, offset, pageSize)
    }

    fun generateHash(variable: String): String {
        val md = MessageDigest.getInstance("MD5")
        val digested = md.digest(variable.toByteArray())
        return digested.joinToString("") {
            String.format("%02x", it)
        }
    }
}

【问题讨论】:

  • 如果进入getHeroes方法,传入什么值?尝试记录/调试它。
  • 值为0的整数
  • HeroesRepository - 上课吧?打开?或者你使用mockito-inline?你也可以试试doReturn(heroesPublishSubject.singleOrError()).when(heroesRepository.getHeroes(ArgumentMatchers.anyInt()))吗?
  • 是的 HeroesRepository 是一个类。与 doReturn 也进入 getHeroes 方法。
  • 公开课? Common mockito 不能模拟 Kotlin 中未公开的课程。那就把这个类的源码贴出来吧。

标签: kotlin mockito


【解决方案1】:

在不添加其他依赖项的情况下,您可以在某处将 @Mock 注释替换为辅助函数:

inline fun <reified T> mock(): T =
        Mockito.mock(T::class.java)

// To avoid having to use backticks for "when"
fun <T> whenever(methodCall: T): OngoingStubbing<T> =
        Mockito.`when`(methodCall)

然后在你的测试中:

val heroesRepository: HeroesRepository = mock()

@Test
fun yourTest() {
    whenever(heroesRepository.getHeroes(ArgumentMatchers.anyInt()))
        .thenReturn(heroesPublishSubject.singleOrError())
}

就像你以前一样。这应该可行,因为您不希望 Mockito 处理它似乎正在努力解决的@Mock lateinit var,而是自己实例化模拟。

【讨论】:

    【解决方案2】:

    Mockito 与 kotlin 不太兼容,您可以改用 mockito-kotlin 资源。 看看这个参考: https://github.com/nhaarman/mockito-kotlin

    您可以像这样轻松地模拟对象:

    val heroesRepository = mock<HeroesRepository>()
    

    那么你就可以像使用mockito一样使用它了

    【讨论】:

      【解决方案3】:

      FWIW,when 语句只是调用实际函数的原因是因为函数本身(getHeroes)没有标记为open

      因此,即使该类是非最终的,该方法也是最终的并且不是模拟的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-07-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-07
        • 1970-01-01
        相关资源
        最近更新 更多