android - 尽管 Realm 被模拟,但实际的 close() 方法被调用

标签 android unit-testing kotlin realm mockito

我有一个相当简单的 save() 方法来保存 RealmModel,在保存 realm.close() 之后调用,因为数据库不再需要。

问题:尽管使用 mockito 模拟了 Realm,但调用了实际的 close() 方法。这会导致异常:

IllegalStateException: Realm access from incorrect thread. Realm instance can only be closed on the thread it was created.

mockito 不能模拟 Realm 吗?我不想为了测试这个案例而包含 PowerMock :D

使用 realm-gradle-plugin 5.0.0 测试


测试类

import io.realm.Realm
import io.realm.RealmModel

class TestedClass {

    fun save(realm: Realm, objectToBeSaved: RealmModel) {
        // Persist your data in a transaction
        realm.executeTransaction {
            // Using executeTransaction with a lambda reduces code size
            // and makes it impossible to forget to commit the transaction.
            it.copyToRealm(objectToBeSaved)
        }
        // Close database after saving (this causes the exception)
        realm.close()
    }
}

单元测试

import com.nhaarman.mockito_kotlin.any
import com.nhaarman.mockito_kotlin.mock
import com.nhaarman.mockito_kotlin.verify

@Test
fun save() {
    val testedClass = TestedClass()
    val mockRealm: Realm = mock()
    val objectToBeSaved: RealmModel = mock()

    testedClass.save(mockRealm, objectToBeSaved) // this causes the exception

    verify(mockRealm).executeTransaction(any())
    verify(mockRealm).copyToRealm(objectToBeSaved)
    verify(mockRealm).close()
}

最佳答案

解决方案是新的 Realm 版本。

似乎在 realm-gradle-plugin 5.0.05.3.1 之间的某处,这个问题在 Realm 库端得到了修复,即使我找不到关于 changelog 的任何文档提到它。

这就是我最终必须完全测试 TestedClass


通过单元测试

import com.nhaarman.mockito_kotlin.argumentCaptor
import com.nhaarman.mockito_kotlin.inOrder
import com.nhaarman.mockito_kotlin.mock
import com.nhaarman.mockito_kotlin.verifyNoMoreInteractions

@Test
fun save() {
    val testedClass = TestedClass()
    val mockRealm: Realm = mock()
    val objectToBeSaved: RealmModel = mock()
    val captor = argumentCaptor<Realm.Transaction>()

    testedClass.save(mockRealm, objectToBeSaved)

    inOrder(mockRealm).apply {
        verify(mockRealm).executeTransaction(captor.capture())
        verify(mockRealm).close()

        // Now make sure the lambda passed to executeTransaction() does the right thing
        captor.firstValue.execute(mockRealm)

        verify(mockRealm).copyToRealm(objectToBeSaved)
        verifyNoMoreInteractions(mockRealm)
    }
}

关于android - 尽管 Realm 被模拟,但实际的 close() 方法被调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49667400/

相关文章:

android - 确定何时取消随机通知,或何时触发 PendingIntent

node.js - nodejs 单元测试 PubSub.publish 不发送数据

kotlin - 扇出/扇入 - 关闭结果 channel

kotlin - 防止 Kotlin 强制 Java 查看通配符类型

nullable - Kotlin mutableMap.put 返回可为空

android - 如何将信息包含到我的 android 应用程序编译后?

java - 致命异常 : android. app.RemoteServiceException : can't deliver broadcast at android. os.Handler.dispatchMessage

android - HTC webview 问题 .getting force close

ruby-on-rails - 当我想测试我的助手类时,无法在 ActionView::TestCase 中使用 flash

vue.js - 如何用 Jest + Vuejs 模拟 window.location.href?