首页 > 解决方案 > 当被测试类而不是直接调用时,Mockito 的 `thenReturn` 返回 `null` 而不是 Pair(null."text")

问题描述

测试和 Mockito 初学者在这里,所以我希望这只是一些简单的错误。
编辑它很可能是由于功能是suspend功能

我的测试崩溃了,因为Mockito返回null应该返回 non-nullable 的地方Pair。在实时环境中,此代码工作正常(无 NPE),但我无法使用 Mockito 使测试通过。
令人不安的模拟:

val mks = mock(MyKeyStore::class.java)
`when`(mks.createKeyStore(user,pass)).thenReturn(Pair(null, "userExists"))

MyKeyStore.createKeyStore()返回不可为空Pair

suspend fun createKeyStore(user: String, ksPass: String): Pair<KeyStore?, String>

mks.createKeyStore()UserRepo.createUser()
UserRepo 崩溃调用,因为测试考虑了ksResult == null,根据定义,它是不可为空的。当我将其更改为可为空时,代码根本无法编译,所以我认为它与 Mockito 设置有关。

class UserRepo(private val myKeyStore: MyKeyStore) {
    suspend fun createUser(user: String, p0: String, p1: String): Pair<Boolean, String> =
        withContext(Dispatchers.IO) {
            return@withContext if (p0 == p1) {
                val ksResult = myKeyStore.createKeyStore(user, p0)
                ksResult.first?.let { //line where NPE crash leads
                    val keyResult = myKeyStore.createKeyDB(user, p0)
                    keyResult.first?.let { Pair(true, keyResult.second) } ?: run { Pair(false, keyResult.second) }
                } ?: run { Pair(false, ksResult.second) }
            } else Pair(false, myKeyStore.mPasswordsNotMatching)
        }
}

全面测试

    @Test
    fun createUserFailDueToUserExisting() = runBlocking() {
        val user = "user"
        val pass = "pass"
        val mks = mock(MyKeyStore::class.java)
        `when`(mks.createKeyStore(user,pass)).thenReturn(Pair(null, "userExists"))
        println(mks.createKeyStore(user,pass)) // this actually prints the pair correctly
        val repo = UserRepo(mks)
        val result = repo.createUser(user,pass,pass) // NPE crash, but why?
        assertFalse(result.first)
        assertTrue(result.second == "userExists")
    }

如何将模拟配置为返回Pair而不是null

标签: androidkotlinmockito

解决方案


这是因为函数是suspend函数,指定调度runBlocking程序为我修复了它,
我找到了答案:testing coroutines in Android

    @Test
    fun createUserFailDueToUserExisting() = runBlocking(Dispatchers.IO) {
        val user = "user"
        val pass = "pass"
        val mks = mock(MyKeyStore::class.java)
        `when`(mks.createKeyStore(user, pass)).thenReturn(Pair(null, "userExists"))
        println(mks.createKeyStore(user, pass))
        val repo = UserRepo(mks)
        val result = repo.createUser(user, pass, pass)
        assertFalse(result.first)
        assertTrue(result.second == "userExists")
    }

推荐阅读