Search code examples
swiftunit-testingmigrationrealm

Test in-memory Realm migration


We are trying to Unit test a Realm migration process using XCTest. Our idea is to prepare an in-memory Realm when the test is set up. That realm will contain a set of models stored, simulating some starting conditions.

During the test we would like to simulate a migration process and check the final state of our migrated Realm.

We configure the first Realm using a Configuration factory:

func getConfiguration() -> Realm.Configuration {
    return Realm.Configuration(inMemoryIdentifier: "AppTest", 
        readOnly: false, 
        schemaVersion: 10, 
        migrationBlock: nil)
}

We then insert all the objects to simulate our starting condition. When we access our Realm, this first configuration is retrieved and used. We also set it as our default configuration before we instantiate our Realm for the first time:

Realm.Configuration.defaultConfiguration = getConfiguration()

When the test is launched, we try to simulate a migration by trying to get a new instance of Realm, passing another configuration to its initialiser:

func getConfiguration() -> Realm.Configuration {
    return Realm.Configuration(inMemoryIdentifier: "AppMigrationTest",
        readOnly: false, 
        schemaVersion: 21, 
        migrationBlock: { (migration: RealmSwift.Migration, oldSchemaVersion: UInt64) in
            // Migration code here
            }, 
        deleteRealmIfMigrationNeeded: false, 
        shouldCompactOnLaunch: nil, 
        objectTypes: nil)
   }

We also set this new Configuration as our default.

We have tried using the same inMemoryIdentifier for both configurations. When we do it, the new Realm makes use of the initial Configuration and no migration is performed. It makes sense that the Realm caches the configuration internally anyway.

If we use different identifiers, then the migration block is not performed. Understanding they both are considered different Realms.

We would like to know if our approach is totally incorrect. Or if we are missing any bit to complete this test successfully. Is there any other way to test that a migration block actually migrates correctly, using in-memory Realms?


Solution

  • A migration inherently cannot be run on an in-memory Realm. In-memory Realms only exist until they are closed, and a migration cannot be run on a Realm which is already open. You will need to use a Realm on disk to test migration logic (and just delete the Realm at the end of the test).