在调用保存save()
之后,我有一个相当简单的RealmModel
方法来保留realm.close()
,因为不再需要数据库。
问题:虽然Realm是使用mockito进行模拟的,但实际调用了close()
方法。这会导致异常:
IllegalStateException:从错误的线程访问Realm。 Realm实例只能在创建它的线程上关闭。
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()
}
答案 0 :(得分:1)
解决方案是新的Realm版本。
似乎在realm-gradle-plugin
5.0.0 和 5.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)
}
}
答案 1 :(得分:0)
在2.x天里,Realm中有很多最终的类和方法,所以你无法模仿它。
我做了一个简单的包装类来解决它,在我的代码中使用它并嘲笑它
open class RealmInstance(val realm: Realm): Closeable by realm {
open fun delete(clazz: Class<out RealmModel>) {
realm.delete(clazz)
}
open fun insertOrUpdate(realmModel: RealmModel) {
realm.insertOrUpdate(realmModel)
}
open fun insertOrUpdate(objects: Collection<RealmModel>?) {
realm.insertOrUpdate(objects)
}
open fun <E : RealmModel> where(clazz: Class<E>): RealmQueryInstance<E> {
return RealmQueryInstance(realm.where(clazz))
}
open fun <E: RealmModel> copyFromRealm(realmObject: E): E {
return realm.copyFromRealm(realmObject)
}
open fun beginTransaction() {
realm.beginTransaction()
}
open fun commitTransaction() {
realm.commitTransaction()
}
open fun <T: RealmObject> copyToRealmOrUpdate(realmObject: T): T {
return realm.copyToRealmOrUpdate(realmObject)
}
open fun <T: RealmObject> copyToRealmOrUpdate(realmList: RealmList<T>): List<T> {
return realm.copyToRealmOrUpdate(realmList)
}
}
但是现在据我所知,Realm
类不再是最终版本了,你应该可以用Mockito来模拟它: