Android O 迁移测试:Room

来源:互联网 发布:从linux虚拟机提取程序 编辑:程序博客网 时间:2024/06/06 03:30


在之前的一篇文章中,我们介绍了一下构件组件,其中就提到了使用 Room 来进行数据库操作。但我们也有注意到,如果您错误地实施迁移,最严重的结果可能会导致您的应用崩溃或丢失用户数据。


除此之外,Migration.migrate 在编译时不会检查在方法中执行的 SQL 语句,这导致了更多的问题。了解到这个情况之后,对迁移进行测试就成了一项必做任务。 Room 提供了 MigrationTestHelper 测试工具,这一工具允许您:

  • 在给定的版本中创建一个数据库

  • 在数据库上运行一组给定的迁移

  • 验证数据库 schema


当然,Room 不会验证数据库中的数据本身。这是您需要亲自去实现的东西。

以下是您需要了解的有关 Room 迁移测试的内容。



工作原理

为了进行迁移测试,Room 需要知道您当前数据库版本的几个要素:版本号、Entity、Identity Hash,以及为创建和更新 room_master_table 而做出的查询请求。所有这些都由 Room 在编译时自动生成,并存储在schema JSON 文件中。


在 build.gradle 文件中指定一个文件夹,来放置这些生成的 schema JSON 文件。在更新 schema 时,最终会出现一些 JSON 文件,每个版本都将有一个对应的文件。确保将每个生成的文件提交给源代码管理工具。下次再次增加版本号码时,Room 可以使用 JSON 文件进行测试。



先决条件

要生成 JSON 文件,请使用以下内容更新 build.gradle 文件:

1. 定义 schema 位置

defaultConfig {
 javaCompileOptions {
           annotationProcessorOptions {
               arguments = ["room.schemaLocation":
                               "$projectDir/schemas".toString()]
           }
       }
}


2. 将 schema 位置添加到源码目录

android {
   
   sourceSets {
       androidTest.assets.srcDirs +=  
                          files("$projectDir/schemas".toString())
   }


3. 将 Room 测试库添加到依赖列表中

dependencies {

androidTestImplementation    
               “android.arch.persistence.room:testing:1.0.0-alpha5”
}



迁移测试规则

创建数据库和 schema,打开和关闭数据库,运行迁移 —— 您几乎需要为每个测试编写大量这样的样板代码。为了避免过度重复劳动,请在迁移测试类中使用 MigrationTestHelper 测试工具。


为了创建数据库以及验证迁移,MigrationTestHelper 很大程度上依赖于生成的 JSON 文件。

@Rule
public MigrationTestHelper testHelper =
       new MigrationTestHelper(
               InstrumentationRegistry.getInstrumentation(),
               <your_database_class>.class.getCanonicalName(),
               new FrameworkSQLiteOpenHelperFactory());


您可以在特定版本中创建数据库:

// Create the database with version 2
SupportSQLiteDatabase db =
                        testHelper.createDatabase(TEST_DB_NAME, 2);


您可以运行一组迁移,并自动验证 schema 是否更新无误:

db = testHelper.runMigrationsAndValidate(TEST_DB_NAME, 4, validateDroppedTables, MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4);



实施测试

测试策略很简单:

  1. 在特定版本中打开数据库;

  2. 插入一些数据;

  3. 运行迁移并验证 schema;

  4. 检查数据库中是否有正确的数据。


例如,数据库的版本 3 添加了一个新列:date 。因此,当测试从版本 2 到版本 3 的迁移时,我们检查插入到版本 2 的数据的有效性,也是我们新列的默认值。我们的 AndroidJUnitTest 看起来是这样的:

@Test
public void migrationFrom2To3_containsCorrectData() throws
                                                      IOException {
   // Create the database in version 2
   SupportSQLiteDatabase db =
                        testHelper.createDatabase(TEST_DB_NAME, 2);
   // Insert some data
   insertUser(USER.getId(), USER.getUserName(), db);
   //Prepare for the next version
   db.close();

   // Re-open the database with version 3 and provide MIGRATION_1_2  
   // and MIGRATION_2_3 as the migration process.
   testHelper.runMigrationsAndValidate(TEST_DB_NAME, 3,  
             validateDroppedTables, MIGRATION_1_2, MIGRATION_2_3);

   // MigrationTestHelper automatically verifies the schema  
   //changes, but not the data validity
   // Validate that the data was migrated properly.
   User dbUser = getMigratedRoomDatabase().userDao().getUser();
   assertEquals(dbUser.getId(), USER.getId());
   assertEquals(dbUser.getUserName(), USER.getUserName());
   // The date was missing in version 2, so it should be null in
   //version 3
   assertEquals(dbUser.getDate(), null);
}



测试从 SQLiteDatabase 到 Room 的迁移

从标准 SQLiteDatabase 到 Room 的步骤虽然乍一看很直观,但我们觉得有必要详细介绍如何测试迁移实现。


因为原本的数据库没有使用 Room 实现,自然我们就没有相应的 JSON 文件,因此我们无法使用 MigrationTestHelper 创建数据库。


我们需要这么做:

  1. 扩展 SQLiteOpenHelper 类,并在 onCreate 执行创建数据库表的 SQL 查询操作;

  2. 在 @Before 测试方法中,创建数据库;

  3. @After 测试方法中,清除数据库;

  4. 使用 SQLiteOpenHelper ,来插入测试所需的数据,检查从 SQLiteDatabase 版本迁移到使用 Room 的版本;

  5. 使用 MigrationTestHelper 运行迁移和验证 schema;

  6. 检查数据库数据的有效性。


数据库版本 1 使用 SQLiteDatabase 实现,然后在版本 2 中,我们迁移到了 Room,而在版本 3 中,我们添加了一个新的列。检查从版本 1 到 3 的迁移测试如下所示:

@Test
public void migrationFrom1To3_containsCorrectData() throws IOException {
   // Create the database with the initial version 1 schema and    
   //insert a user
   SqliteDatabaseTestHelper.insertUser(1, USER.getUserName(), sqliteTestDbHelper);

   // Re-open the database with version 3 and provide MIGRATION_1_2
   // and MIGRATION_2_3 as the migration process.
   testHelper.runMigrationsAndValidate(TEST_DB_NAME, 3, true,
           MIGRATION_1_2, MIGRATION_2_3);

   // Get the latest, migrated, version of the database
   // Check that the correct data is in the database
   User dbUser = getMigratedRoomDatabase().userDao().getUser();
   assertEquals(dbUser.getId(), 1);
   assertEquals(dbUser.getUserName(), USER.getUserName());
   // The date was missing in version 2, so it should be null in  
   //version 3
   assertEquals(dbUser.getDate(), null);
}



挽起袖子试试吧!

这里有一个示例 App:

https://github.com/googlesamples/android-architecture-components/tree/master/PersistenceMigrationsSample


您可以在此示例应用中查看实现。为了简化比较,每个数据库版本都是以自己的风格实现的,相信看完之后您已经能玩转典型的迁移路径了:

  1. sqlite:使用 SQLiteOpenHelper 和传统的 SQLite 界面;

  2. room :使用 Room 替换实现,并提供到版本 2 的迁移;

  3. room2:将数据库更新为新 schema,版本 3;

  4. room3 将数据库更新为新的版本 4。提供从版本 2 到 3,版本 3 到 4,以及版本 1 到 4 的迁移路径。


使用 Room,您可以很容易地实施和测试迁移。MigrationTestHelper 允许您在任何版本打开数据库、运行迁移,并且只需几行代码就可以验证 schema。


您是否已经开始使用 Room 并实施迁移?如果答案是肯定的话,请在下面写出评论,让我们了解您的想法和问题。



推荐阅读:

全新 Android 构建组件到底有多好用?

Android 8.0 Oreo 画中画模式

Android 8.0 Oreo 现已推出!

Android O 迁移应用官方指南

Android O 行为变更官方指南


原创粉丝点击