Skip to content
AB

Testing Room Migrations Instead of Hoping They Work

Upgrade real historical schemas and verify both data preservation and new database invariants.

Ashish BhakhandPublished

A fresh-install test never exercises the path existing users take. They open a database created by an older release and run every required migration.

Export Room schemas to version control and use the migration test helper to create an old database, insert representative rows, migrate, and validate the result.

Code
helper.createDatabase(TEST_DB, 3).apply {
    execSQL("insert into workouts(id, name) values('w1', 'Strength')")
    close()
}

val db = helper.runMigrationsAndValidate(TEST_DB, 5, true, MIGRATION_3_4, MIGRATION_4_5)

Schema validation proves columns and indexes. Add assertions for transformed data, defaults, tombstones, and uniqueness behavior.

Test the complete supported upgrade path, not only the newest pair. A migration can work from version 4 while users on version 2 still fail.

Destructive fallback is appropriate only for data the application can safely recreate. It is not a migration strategy for offline user-created records.

Keep migration SQL explicit and review lock or copy cost on large tables. A passing test proves correctness on its fixture; production volume still needs operational judgment.

Database upgrades are part of the app's public promise. Existing users should retain their data as reliably as new users create it.

← Back to all writing