当被测试 class 而不是直接调用时,Mockito 的 `thenReturn` returns `null` 而不是 Pair(null."text")
Mockito's `thenReturn` returns `null` instead of Pair(null."text") when called by tested class and not directly
这里是测试和 Mockito 初学者,所以我希望这只是一些简单的错误。
编辑这很可能是因为函数是 suspend
函数
我的测试崩溃是因为 Mockito
returns null
它应该 return 不可为空 Pair
。在实时环境中,此代码运行良好(无 NPE),但我无法使用 Mockito 通过测试。
麻烦的模拟:
val mks = mock(MyKeyStore::class.java)
`when`(mks.createKeyStore(user,pass)).thenReturn(Pair(null, "userExists"))
MyKeyStore.createKeyStore()
returns 不可为空 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")
}
如何将模拟配置为 return Pair
而不是 null
?
因为函数是 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")
}
这里是测试和 Mockito 初学者,所以我希望这只是一些简单的错误。
编辑这很可能是因为函数是 suspend
函数
我的测试崩溃是因为 Mockito
returns null
它应该 return 不可为空 Pair
。在实时环境中,此代码运行良好(无 NPE),但我无法使用 Mockito 通过测试。
麻烦的模拟:
val mks = mock(MyKeyStore::class.java)
`when`(mks.createKeyStore(user,pass)).thenReturn(Pair(null, "userExists"))
MyKeyStore.createKeyStore()
returns 不可为空 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")
}
如何将模拟配置为 return Pair
而不是 null
?
因为函数是 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")
}