Android 如何对领域迁移进行单元测试?

Android 如何对领域迁移进行单元测试?,android,realm,Android,Realm,我正在尝试对Realm上的迁移进行单元测试。我的主要问题是:如何维护RealmObject的不同模式版本,以便能够创建旧对象的实例,进行迁移,然后根据新模式版本检查是否正确 我开始尝试保留不同的模式版本,但它不会编译,因为对象具有相同的名称,尽管它们位于不同的包中。在Realm,我们通过将旧的Realm文件存储为资产来测试迁移机制(请参阅),然后在迁移测试后编写测试以检查结果(请参阅).在来自的帮助下,我找到了执行领域迁移单元测试的方法 一步一步地,这是您构建测试的方式: 从特定状态创建领域实

我正在尝试对Realm上的迁移进行单元测试。我的主要问题是:如何维护RealmObject的不同模式版本,以便能够创建旧对象的实例,进行迁移,然后根据新模式版本检查是否正确


我开始尝试保留不同的模式版本,但它不会编译,因为对象具有相同的名称,尽管它们位于不同的包中。

在Realm,我们通过将旧的Realm文件存储为资产来测试迁移机制(请参阅),然后在迁移测试后编写测试以检查结果(请参阅).

在来自的帮助下,我找到了执行领域迁移单元测试的方法

一步一步地,这是您构建测试的方式:

  • 从特定状态创建领域实例。过去的某个架构版本(要迁移的旧架构)
  • 创建
    RealmConfiguration
    ,如下所示:(1)将项目的架构版本升级到最新版本(2)与上面的领域实例保持相同的名称(3)添加将运行迁移的迁移代码
  • 从上面创建的
    RealmConfiguration
    中创建领域实例。如果迁移成功运行,则不会引发异常。您将成功地将代码从该状态迁移到当前应用的领域架构版本

假设在您第一次开始构建应用程序时,您的应用程序先前在架构版本0上运行。现在,您在模式版本1上进行了一些更改。您正在编写测试,以查看是否可以成功地从版本0迁移到版本1

在版本0创建领域数据库的领域文件。我通常做的是使用git提交签出我的代码,当我的应用程序使用版本0时,运行我的应用程序创建领域数据库,然后将领域文件复制到我的计算机文件系统。将此域文件存储在应用程序项目的
androidTest/assets
assets目录中

将文件复制到项目中。这是您将用于从
androidTest/assets
Realm文件创建领域实例的内容

创建测试。以下是我从运行的迁移测试中获得的一些示例代码:

@RunWith(AndroidJUnit4::class)
open class MigrationTest {

    @get:Rule open val configFactory = TestRealmConfigurationFactory()
    @get:Rule open val thrown = ExpectedException.none()

    private lateinit var context: Context

    @Before
    fun setup() {
        context = InstrumentationRegistry.getInstrumentation().context
    }

    @Test(expected = RealmMigrationNeededException::class)
    @Throws(Exception::class)
    fun migrate_migrationNeededIsThrown() {
        val REALM_NAME = "0.realm"
        val realmConfig = RealmConfiguration.Builder()
                .name(REALM_NAME)
                .schemaVersion(0)
                .build()
        configFactory.copyRealmFromAssets(context, REALM_NAME, realmConfig)

        // should fail because my code base realm models have changed *since* this 0.realm file.
        // When you want to get a realm instance, it will take what realm objects are already in memory (mapped by the "name" property of the RealmConfiguration) and it will compare it to the models in the application. If they are different, a realm migration exception will be thrown. So, you need to make sure to add Realm migrations to your code at all times.
        val realm = Realm.getInstance(realmConfig)
        realm.close()
    }

    @Test fun migrate_migrateFrom0toLatest() {
        val REALM_NAME = "0.realm"
        val realmConfig = RealmConfiguration.Builder()
                .name(REALM_NAME)
                .schemaVersion(RealmInstanceManager.schemaVersion)
                .migration { dynamicRealm, oldVersion, newVersion ->
                    val schema = dynamicRealm.schema

                    for (i in oldVersion until newVersion) {
                        RealmInstanceManager.migrations[i.toInt()].runMigration(schema)
                    }
                }
                .build()
        configFactory.copyRealmFromAssets(context, REALM_NAME, realmConfig)

        val realm = Realm.getInstance(realmConfig)
        realm.close()
    }

    // convenient method to generate 1 realm file in app directory to be able to copy to assets directory for the next migration test when schema version changes.
    @Test fun createFileForCurrentVersionToCopyToAssetsFile() {
        val REALM_NAME = "${RealmInstanceManager.schemaVersion}.realm"
        val realmConfig = RealmConfiguration.Builder()
                .name(REALM_NAME)
                .schemaVersion(RealmInstanceManager.schemaVersion)
                .build()

        Realm.deleteRealm(realmConfig)
        val realm = Realm.getInstance(realmConfig)
        realm.close()
    }

}
作为参考,这里是我的
RealmInstanceManager
和其他附带文件,我创建这些文件是为了隔离迁移

open class RealmInstanceManager(private val userManager: UserManager) {

    companion object {
        val migrations: List<RealmSchemaMigration> = listOf(
                Migration1()
        )

        var schemaVersion: Long = 0L
            get() = migrations.size.toLong()
    }

}
最后,我的
RealmSchemaMigration
界面:

interface RealmSchemaMigration {

    fun runMigration(schema: RealmSchema)

}
我发现上面的文件和接口配置是一种很好的方法,可以在我的项目中管理迁移文件,以便运行测试和应用程序本身


真的,你完了。迁移测试在函数
migrate\u migrateFrom0talest()
中,我从模式版本0(名为“0.Realm”)获取域文件资产,并将其迁移到代码库中的最新版本。函数
createFileForCurrentVersionToAssetFile()
不是必需的,但我喜欢使用它,因为在运行测试后,我可以将设备上新创建的领域文件复制到我的资产目录中,以用于我运行的下一个迁移测试。使用我上面解释的git签出方法要容易得多

如何执行“将旧域文件存储为资产”部分??可以将域文件存储为资产()中的任何其他文件。也许能帮上忙。为了测试的目的?是的,我们手动制作副本并将其存储在资产中。但是我们的目标是不同的,因为我们正在测试迁移机制是否在正确的时间调用ie。
interface RealmSchemaMigration {

    fun runMigration(schema: RealmSchema)

}