MigrationTestHelper



A class that can help test and verify database creation and migration at different versions with different schemas.

Common usage of this helper is to create a database at an older version first and then attempt a migration and validation:

@Test
fun
migrationTest() {
val migrationTestHelper = getMigrationTestHelper()
// Create the database at version 1
val newConnection = migrationTestHelper.createDatabase(1)
// Insert some data that should be preserved
newConnection.execSQL("INSERT INTO Pet (id, name) VALUES (1, 'Tom')")
newConnection.close()

// Migrate the database to version 2
val migratedConnection =
migrationTestHelper.runMigrationsAndValidate(2, listOf(MIGRATION_1_2)))
migratedConnection.prepare("SELECT * FROM Pet).use { stmt ->
// Validates data is preserved between migrations.
assertThat(stmt.step()).isTrue()
assertThat(stmt.getText(1)).isEqualTo("Tom")
}
migratedConnection.close()
}

The helper relies on exported schemas so androidx.room.Database.exportSchema should be enabled. Schema location should be configured via Room's Gradle Plugin (id 'androidx.room'):

room {
schemaDirectory("$projectDir/schemas")
}

The helper is then instantiated to use the same schema location where they are exported to. See platform-specific documentation for further configuration.

Summary

Public constructors

MigrationTestHelper(
    instrumentation: Instrumentation,
    databaseClass: Class<RoomDatabase>
)

Creates a new migration helper.

android
MigrationTestHelper(
    instrumentation: Instrumentation,
    assetsFolder: String,
    openFactory: SupportSQLiteOpenHelper.Factory
)

This function is deprecated. Cannot be used to run migration tests involving auto migrations.

android
MigrationTestHelper(
    instrumentation: Instrumentation,
    databaseClass: Class<RoomDatabase>,
    specs: List<AutoMigrationSpec>,
    openFactory: SupportSQLiteOpenHelper.Factory
)

Creates a new migration helper.

android
MigrationTestHelper(
    instrumentation: Instrumentation,
    file: File,
    driver: SQLiteDriver,
    databaseClass: KClass<RoomDatabase>,
    databaseFactory: () -> RoomDatabase,
    autoMigrationSpecs: List<AutoMigrationSpec>
)

Creates a new migration helper.

android
MigrationTestHelper(
    schemaDirectoryPath: Path,
    databasePath: Path,
    driver: SQLiteDriver,
    databaseClass: KClass<RoomDatabase>,
    databaseFactory: () -> RoomDatabase,
    autoMigrationSpecs: List<AutoMigrationSpec>
)
android
MigrationTestHelper(
    schemaDirectoryPath: String,
    fileName: String,
    driver: SQLiteDriver,
    databaseClass: KClass<RoomDatabase>,
    databaseFactory: () -> RoomDatabase,
    autoMigrationSpecs: List<AutoMigrationSpec>
)
N

Public functions

open Statement
android
open Statement
android
open Unit

Registers a database connection to be automatically closed when the test finishes.

android
open Unit

Registers a database connection to be automatically closed when the test finishes.

android
SQLiteConnection
createDatabase(version: Int)

Creates the database at the given version.

Cmn
android
N
open SupportSQLiteDatabase
createDatabase(name: String, version: Int)

Creates the database in the given version.

android
Unit
N
SQLiteConnection
runMigrationsAndValidate(version: Int, migrations: List<Migration>)

Runs the given set of migrations on the existing database once created via createDatabase.

Cmn
android
N
open SupportSQLiteDatabase
runMigrationsAndValidate(
    name: String,
    version: Int,
    validateDroppedTables: Boolean,
    vararg migrations: Migration
)

Runs the given set of migrations on the provided database.

android

Protected functions

open Unit
android
open Unit
android
open Unit
finished(description: Description?)
android
open Unit
finished(description: Description?)
android
open Unit

This function is deprecated. Deprecated in Java

android
open Unit

This function is deprecated. Deprecated in Java

android
open Unit
android
open Unit
android
open Unit
starting(description: Description?)
android
open Unit
android
open Unit
android
open Unit
android

Public constructors

MigrationTestHelper

MigrationTestHelper(
    instrumentation: Instrumentation,
    databaseClass: Class<RoomDatabase>
)

Creates a new migration helper. It uses the instrumentation context to load the schema (falls back to the app resources) and the target context to create the database.

When the MigrationTestHelper is created with this constructor configuration then only createDatabase and runMigrationsAndValidate that return SupportSQLiteDatabase can be used.

Parameters
instrumentation: Instrumentation

The instrumentation instance.

databaseClass: Class<RoomDatabase>

The Database class to be tested.

MigrationTestHelper

MigrationTestHelper(
    instrumentation: Instrumentation,
    assetsFolder: String,
    openFactory: SupportSQLiteOpenHelper.Factory = FrameworkSQLiteOpenHelperFactory()
)

Creates a new migration helper. It uses the instrumentation context to load the schema (falls back to the app resources) and the target context to create the database.

When the MigrationTestHelper is created with this constructor configuration then only createDatabase and runMigrationsAndValidate that return SupportSQLiteDatabase can be used.

Parameters
instrumentation: Instrumentation

The instrumentation instance.

assetsFolder: String

The asset folder in the assets directory.

openFactory: SupportSQLiteOpenHelper.Factory = FrameworkSQLiteOpenHelperFactory()

factory for creating an SupportSQLiteOpenHelper

MigrationTestHelper

MigrationTestHelper(
    instrumentation: Instrumentation,
    databaseClass: Class<RoomDatabase>,
    specs: List<AutoMigrationSpec>,
    openFactory: SupportSQLiteOpenHelper.Factory = FrameworkSQLiteOpenHelperFactory()
)

Creates a new migration helper. It uses the instrumentation context to load the schema (falls back to the app resources) and the target context to create the database.

Instances of classes annotated with androidx.room.ProvidedAutoMigrationSpec have provided using this constructor. MigrationTestHelper will map auto migration spec classes to their provided instances before running and validating the migrations.

When the MigrationTestHelper is created with this constructor configuration then only createDatabase and runMigrationsAndValidate that return SupportSQLiteDatabase can be used.

Parameters
instrumentation: Instrumentation

The instrumentation instance.

databaseClass: Class<RoomDatabase>

The Database class to be tested.

specs: List<AutoMigrationSpec>

The list of available auto migration specs that will be provided to the RoomDatabase at runtime.

openFactory: SupportSQLiteOpenHelper.Factory = FrameworkSQLiteOpenHelperFactory()

factory for creating an SupportSQLiteOpenHelper

MigrationTestHelper

MigrationTestHelper(
    instrumentation: Instrumentation,
    file: File,
    driver: SQLiteDriver,
    databaseClass: KClass<RoomDatabase>,
    databaseFactory: () -> RoomDatabase = { findAndInstantiateDatabaseImpl(databaseClass.java) },
    autoMigrationSpecs: List<AutoMigrationSpec> = emptyList()
)

Creates a new migration helper. It uses the instrumentation context to load the schema (falls back to the app resources) and the target context to create the database.

When the MigrationTestHelper is created with this constructor configuration then only createDatabase and runMigrationsAndValidate that return SQLiteConnection can be used.

Parameters
instrumentation: Instrumentation

The instrumentation instance.

file: File

The database file.

driver: SQLiteDriver

A driver that opens connection to a file database. A driver that opens connections to an in-memory database would be meaningless.

databaseClass: KClass<RoomDatabase>

The androidx.room.Database annotated class.

databaseFactory: () -> RoomDatabase = { findAndInstantiateDatabaseImpl(databaseClass.java) }

An optional factory function to create an instance of the databaseClass. Should be the same factory used when building the database via androidx.room.Room.databaseBuilder.

autoMigrationSpecs: List<AutoMigrationSpec> = emptyList()

The list of androidx.room.ProvidedAutoMigrationSpec instances for androidx.room.AutoMigrations that require them.

MigrationTestHelper

MigrationTestHelper(
    schemaDirectoryPath: Path,
    databasePath: Path,
    driver: SQLiteDriver,
    databaseClass: KClass<RoomDatabase>,
    databaseFactory: () -> RoomDatabase = { findAndInstantiateDatabaseImpl(databaseClass.java) },
    autoMigrationSpecs: List<AutoMigrationSpec> = emptyList()
)
Parameters
schemaDirectoryPath: Path

The schema directory where schema files are exported.

databasePath: Path

Name of the database.

driver: SQLiteDriver

A driver that opens connection to a file database. A driver that opens connections to an in-memory database would be meaningless.

databaseClass: KClass<RoomDatabase>

The androidx.room.Database annotated class.

databaseFactory: () -> RoomDatabase = { findAndInstantiateDatabaseImpl(databaseClass.java) }

An optional factory function to create an instance of the databaseClass. Should be the same factory used when building the database via androidx.room.Room.databaseBuilder.

autoMigrationSpecs: List<AutoMigrationSpec> = emptyList()

The list of androidx.room.ProvidedAutoMigrationSpec instances for androidx.room.AutoMigrations that require them.

MigrationTestHelper

MigrationTestHelper(
    schemaDirectoryPath: String,
    fileName: String,
    driver: SQLiteDriver,
    databaseClass: KClass<RoomDatabase>,
    databaseFactory: () -> RoomDatabase = { findDatabaseConstructorAndInitDatabaseImpl(databaseClass) },
    autoMigrationSpecs: List<AutoMigrationSpec> = emptyList()
)
Parameters
schemaDirectoryPath: String

The schema directory where schema files are exported.

fileName: String

Name of the database.

driver: SQLiteDriver

A driver that opens connection to a file database. A driver that opens connections to an in-memory database would be meaningless.

databaseClass: KClass<RoomDatabase>

The androidx.room.Database annotated class.

databaseFactory: () -> RoomDatabase = { findDatabaseConstructorAndInitDatabaseImpl(databaseClass) }

The factory function to create an instance of the databaseClass. Should be the same factory used when building the database via androidx.room.Room.databaseBuilder.

autoMigrationSpecs: List<AutoMigrationSpec> = emptyList()

The list of androidx.room.ProvidedAutoMigrationSpec instances for androidx.room.AutoMigrations that require them.

Public functions

apply

open fun apply(p0: Statement, p1: Description): Statement

apply

open fun apply(p0: Statement, p1: Description): Statement

closeWhenFinished

open fun closeWhenFinished(db: RoomDatabase): Unit

Registers a database connection to be automatically closed when the test finishes.

This only works if MigrationTestHelper is registered as a Junit test rule via the org.junit.Rule annotation.

Parameters
db: RoomDatabase

The RoomDatabase instance which holds the database.

closeWhenFinished

open fun closeWhenFinished(db: SupportSQLiteDatabase): Unit

Registers a database connection to be automatically closed when the test finishes.

This only works if MigrationTestHelper is registered as a Junit test rule via the org.junit.Rule annotation.

Parameters
db: SupportSQLiteDatabase

The database connection that should be closed after the test finishes.

createDatabase

fun createDatabase(version: Int): SQLiteConnection

Creates the database at the given version.

Once a database is created it can further validate with runMigrationsAndValidate.

Parameters
version: Int

The version of the schema at which the database should be created.

Returns
SQLiteConnection

A database connection of the newly created database.

Throws
kotlin.IllegalStateException

If a new database was not created.

createDatabase

open fun createDatabase(name: String, version: Int): SupportSQLiteDatabase

Creates the database in the given version.

If the database file already exists, it tries to delete it first. If delete fails, throws an exception.

Parameters
name: String

The name of the database.

version: Int

The version in which the database should be created.

Returns
SupportSQLiteDatabase

A database connection which has the schema in the requested version.

finished

fun finished(): Unit

runMigrationsAndValidate

fun runMigrationsAndValidate(
    version: Int,
    migrations: List<Migration> = emptyList()
): SQLiteConnection

Runs the given set of migrations on the existing database once created via createDatabase.

This function uses the same algorithm that Room performs to choose migrations such that the migrations instances provided must be sufficient to bring the database from current version to the desired version. If the database contains androidx.room.AutoMigrations, then those are already included in the list of migrations to execute if necessary. Note that provided manual migrations take precedence over auto migrations if they overlap in migration paths.

Once migrations are done, this functions validates the database schema to ensure the migration performed resulted in the expected schema.

Parameters
version: Int

The final version the database should migrate to.

migrations: List<Migration> = emptyList()

The list of migrations used to attempt the database migration.

Returns
SQLiteConnection

A database connection of the migrated database.

Throws
kotlin.IllegalStateException

If the schema validation fails.

runMigrationsAndValidate

open fun runMigrationsAndValidate(
    name: String,
    version: Int,
    validateDroppedTables: Boolean,
    vararg migrations: Migration
): SupportSQLiteDatabase

Runs the given set of migrations on the provided database.

It uses the same algorithm that Room uses to choose migrations so the migrations instances that are provided to this method must be sufficient to bring the database from current version to the desired version.

After the migration, the method validates the database schema to ensure that migration result matches the expected schema. Handling of dropped tables depends on the validateDroppedTables argument. If set to true, the verification will fail if it finds a table that is not registered in the Database. If set to false, extra tables in the database will be ignored (this is the runtime library behavior).

Parameters
name: String

The database name. You must first create this database via createDatabase.

version: Int

The final version after applying the migrations.

validateDroppedTables: Boolean

If set to true, validation will fail if the database has unknown tables.

vararg migrations: Migration

The list of available migrations.

Throws
kotlin.IllegalStateException

If the schema validation fails.

Protected functions

failed

protected open fun failed(p0: Throwable, p1: Description): Unit

failed

protected open fun failed(p0: Throwable, p1: Description): Unit

finished

protected open fun finished(description: Description?): Unit

finished

protected open fun finished(description: Description?): Unit

skipped

protected open fun skipped(p0: AssumptionViolatedException, p1: Description): Unit

skipped

protected open fun skipped(p0: AssumptionViolatedException, p1: Description): Unit

skipped

protected open fun skipped(p0: AssumptionViolatedException, p1: Description): Unit

skipped

protected open fun skipped(p0: AssumptionViolatedException, p1: Description): Unit

starting

protected open fun starting(description: Description?): Unit

starting

protected open fun starting(p0: Description): Unit

succeeded

protected open fun succeeded(p0: Description): Unit

succeeded

protected open fun succeeded(p0: Description): Unit