簡體   English   中英

Android:測試室遷移

[英]Android: Testing room migration

我有一個遷移,我在其中添加了一個新列遷移定義為

val MIGRATION_20_21: Migration = object : Migration(20, 21) {
    override fun migrate(database: SupportSQLiteDatabase) {
        database.execSQL("ALTER TABLE tests ADD COLUMN deleted INTEGER NOT NULL DEFAULT 0")

    }
}

該領域被用作

@ColumnInfo(name = "deleted") var deleted: Boolean = false,

我有這個遷移的測試用例,看起來像

@Test
@Throws(IOException::class)
fun migrate20to21() {
    var db = helper.createDatabase(TEST_DB, 20).apply {
        
        addTestsToDatabase(this, true)
       
        close()
    }

    db = helper.runMigrationsAndValidate(TEST_DB, 21, true,
            MIGRATION_20_21)

    var cursor = db.query("SELECT * FROM tests WHERE id = ?", arrayOf("id0"))
    MatcherAssert.assertThat(cursor, Is(notNullValue()))
    MatcherAssert.assertThat(cursor.moveToFirst(), `is`(true))
    MatcherAssert.assertThat(cursor.getColumnIndex("deleted"), `is`(38))
    MatcherAssert.assertThat(cursor.getInt(cursor.getColumnIndex("deleted")), `is`(0))

我收到錯誤遷移沒有正確處理:測試我看到預期和找到的表信息有所不同

Expected: deleted=Column{name='deleted', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}, local_created_at=Column{name='local_created_at', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}

Found: deleted=Column{name='deleted', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='0'}

為什么默認值存在差異以及當我將其定義為非空時它如何為空。

為什么默認值存在差異以及當我將其定義為非空時它如何為空

原因是“預期”是從實體派生的(在編譯時),然后與正在/已經打開的實際數據庫的架構(已經“找到”的內容)進行比較,因此您需要更改實體也有一個默認值 0,使用@ColumnInfo(defaultValue = "0")

如果沒有,默認值將為空,即沒有指定默認值。

  • @ColumnInfodefaultValue是在Room 2.2.0中引入的,直到那個版本 DEFAULT 子句(我相信)被忽略並且預期/發現沖突不會出現。

所以實體應該包含

@ColumnInfo(defaultValue = "0")
val deleted: Int = 0
  • 或者代替Int = 0Boolean = false

修正重新更新顯示:-

@ColumnInfo(name = "deleted") var deleted: Boolean = false,

那么你需要使用:-

@ColumnInfo(name = "deleted", defaultValue = "0") var deleted: Boolean = false,

重新評論

謝謝你。 當我說var deleted: Boolean = false 時,是不是和說defaultValue 不一樣?

對了就不一樣了。

為 var/val 設置值會在實例化對象時未提供值時設置字段的值,並有效地為對象分配默認值。

雖然defaultValue = "0"表示列定義在表的列定義中包含DEFAULT 0

例如

 `deleted` INTEGER NOT NULL DEFAULT 0

沒有你得到

 `deleted` INTEGER NOT NULL

這就是 Room EXPECTED(因為它沒有defaultValue = )在你的情況下,根據你的 ALTER 列定義是 FOUND 與預期的不同(沒有 DEFAULT 所以 Room 的解釋是 defaultValue = null)。

在您的情況下, defaultValue = "0" 很重要,因為 0 (false) 將用作 ALTER 之前存在的行的列的值,而 null 可能會導致運行時問題。

使用var deleted: Boolean = false也可能很重要,因為如果在實例化對象時省略該值,它會提供默認值。

  • 也許獲得 Room 期望的最好/最簡單的方法是更改​​您的實體,然后編譯(例如 Ctrl + F9),然后檢查生成的 java (在 Android Studio 中的 Android 視圖中很容易看到),然后找到該類被命名為每用_Impl后綴的@Database類,然后尋找createAllTables方法,其包括預期的表定義。

  • 例如

  • 在此處輸入圖片說明

另一項修正案

關於評論

遷移是否使用了room創建的json文件?

不,除非使用AutoMigration AutoMigration 在編譯時構建遷移代碼(我相信),因此它需要架構並需要 exportSchema = true 和底層 gradle 架構位置指令。

遷移實際上發生在運行時並且不需要(甚至無法訪問已保存的模式,因為我認為它們未包含在 APK 中)。

我當前的版本是 24,但這個字段是在版本 21 中添加的。所以即使我添加了 default = 0,它也只會重新創建 24.json。 這個 20 到 21 的測試用例失敗了,因為 21.json 沒有默認值。

我懷疑這可能是由於不同版本的 Room。 2.2.0之前, defaultValue不是一個選項,因此在比較預期和發現時會被忽略。 請注意,此比較是在執行遷移后進行的(我相信所有遷移)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM