Android Room Migration test fails, although nothing changed

Viewed 859

I am trying to test a Room migration, but the test always fails. There is not even a change in the model. I only increase the version number and the migration is empty - the test still fails. I don't understand what I'm doing wrong.

Let's say we have an entity EntityExample, with two columns a and b. The primary key is composed of both a and b, and we have indices for both columns. The code looks like:

@Entity(primaryKeys = {"a", "b"}, indices = {@Index("a"), @Index("b")})
public class EntityExample {
    @NonNull public Long a;
    @NonNull public Long b;
}

Further, our database in version 1:

@Database(version=1,entities={EntityExample.class})
public abstract class DBExample extends RoomDatabase {
}

and in version 2:

@Database(version=2,entities={EntityExample.class})
public abstract class DBExample extends RoomDatabase {
}

Also, there are the migrations:

public class MigrationExample {
    public final static Migration MIGRATION_1_2 = new Migration(1,2) {
        @Override
        public void migrate(@NonNull SupportSQLiteDatabase database) {

        }
    };
}

To access the schema in tests, in the build.gradle was added:

android {
    sourceSets {
        // Adds exported schema location as test app assets.
        debug.assets.srcDirs += files("$projectDir/schemas".toString())
    }
}

And, finally, the test:

@Config(sdk = Build.VERSION_CODES.O_MR1)
@RunWith(RobolectricTestRunner.class)
public class MigrationExampleTest {

    @Rule
    public MigrationTestHelper helper;

    public MigrationExampleTest() {
        helper = new MigrationTestHelper(InstrumentationRegistry.getInstrumentation(),
                DBExample.class.getCanonicalName(),
                new FrameworkSQLiteOpenHelperFactory());
    }

    @Test
    public void migrationTest() throws IOException {

        SupportSQLiteDatabase dbV1 = helper.createDatabase("migration-test", 1);
        dbV1.close();

        DBExample dbV2 = Room.databaseBuilder(
                InstrumentationRegistry.getInstrumentation().getTargetContext(),
                DBExample.class,
                "migration-test")
                .addMigrations(MigrationExample.MIGRATION_1_2)
                .build();
        dbV2.getOpenHelper().getWritableDatabase();
        dbV2.close();
    }

}

The test fails on the line dbV2.getOpenHelper().getWritableDatabase(); with

java.lang.IllegalStateException: Migration didn't properly handle: EntityExample(....EntityExample).
 Expected:
TableInfo{name='EntityExample', columns={a=Column{name='a', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=1, defaultValue='null'}, b=Column{name='b', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=2, defaultValue='null'}}, foreignKeys=[], indices=[Index{name='index_EntityExample_a', unique=false, columns=[a]}, Index{name='index_EntityExample_b', unique=false, columns=[b]}]}
 Found:
TableInfo{name='EntityExample', columns={a=Column{name='a', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=1, defaultValue='null'}, b=Column{name='b', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=1, defaultValue='null'}}, foreignKeys=[], indices=null}

As you can see (when scrolling the test output to the right), the indices part is missing in the found TableInfo. Also, the primaryKeyPosition for b differs between 1 and 2. I don't understand why, I don't know what exactly causes the test to fail, and I don't know how to fix this. Running the app works, no exceptions are thrown. I checked the schemas, they are completely the same except for the updated version number (see https://justpaste.it/68l2b and https://justpaste.it/3r45p). However, the test fails!

1 Answers

If you haven't yet, you can check this good article on migration testing : https://medium.com/androiddevelopers/testing-room-migrations-be93cdb0d975

Then, in your migration you have to actually migrate the database, execute the SQL to go from 1 to 2, by creating indices for example.

Room handles migration chaining, structure integrity and testing, but not the migration itself. In the documentation https://developer.android.com/training/data-storage/room/migrating-db-versions they do migrations of their database, you should do the same.

Related