Room on Android has a mechanism by which you can export your database schema as JSON, and then validate database migrations against the exported schema in your unit test suite. I've run into a problem on a table with multiple primary keys in which the primary key positions are both 1 after the migration is run. Both V1 and V2 of the schema export, however, have the primary keys listed in the same order. Additionally, the table schema exported to JSON contains an empty list ([]) for indices, whereas the in-memory test database is created with a null value for indices.
I'm curious if this is a bug in Room, or if I'm possibly misusing the test framework. The only change in the given migration is the addition of an entirely new and unrelated table. Here's my test code:
@RunWith(RobolectricTestRunner::class)
class MigrationTest {
@Rule @JvmField
val helper: MigrationTestHelper = MigrationTestHelper(
InstrumentationRegistry.getInstrumentation(),
ApplicationDatabase::class.java.canonicalName,
FrameworkSQLiteOpenHelperFactory()
)
@Test
@Throws(IOException::class)
fun `Test migration from 1 to 2`() {
helper.createDatabase(TEST_DB, 1).apply {
close()
}
helper.runMigrationsAndValidate(TEST_DB, 2, true, MIGRATION_1_2)
}
companion object {
const val TEST_DB = "migration-test"
}
}
When running this test, I get the following error:
java.lang.IllegalStateException: Migration didn't properly handle: Foo
Expected: TableInfo{name='Foo', columns={bar=Column{name='bar', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=1, defaultValue='null'}, baz=Column{name='baz', type='TEXT', affinity='3', notNull=true, primaryKeyPosition=2, defaultValue='null'}}, foreignKeys=[], indices=[]}
found: TableInfo{name='Foo', columns={bar=Column{name='bar', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=1, defaultValue='null'}, baz=Column{name='baz', type='TEXT', affinity='3', notNull=true, primaryKeyPosition=1, defaultValue='null'}}, foreignKeys=[], indices=null}
A snippet of the JSON schema export to show the column ordering is identical in both cases.
1.json:
"tableName": "Foo",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`bar` INTEGER NOT NULL, `baz` INTEGER NOT NULL, PRIMARY KEY(`bar`, `baz`))",
2.json:
"tableName": "Foo",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`bar` INTEGER NOT NULL, `baz` INTEGER NOT NULL, PRIMARY KEY(`bar`, `baz`))",