【问题标题】:Mockito's `thenReturn` returns `null` instead of Pair(null."text") when called by tested class and not directly当被测试类而不是直接调用时,Mockito 的 `thenReturn` 返回 `null` 而不是 Pair(null."text")
【发布时间】:2020-08-20 12:10:00
【问题描述】:

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

我的测试崩溃了,因为Mockito 返回null,它应该返回不可为空的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

【问题讨论】:

  • 最好的建议是尝试通过调试器进行测试。
  • 不是,问题是函数是 suspend 函数,而不是在测试中指定调度程序

标签: android kotlin mockito


【解决方案1】:

这是因为函数是 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")
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-27
    • 2018-11-28
    • 2017-04-11
    相关资源
    最近更新 更多