[英]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")
。
如果沒有,默認值將為空,即沒有指定默認值。
@ColumnInfo
的defaultValue
是在Room 2.2.0中引入的,直到那個版本 DEFAULT 子句(我相信)被忽略並且預期/發現沖突不會出現。所以實體應該包含
@ColumnInfo(defaultValue = "0")
val deleted: Int = 0
Int = 0
, Boolean = 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.