单元测试的数据库资产
database asset for unitTest
对于我的单元测试,我在 SQLite 数据库中收集了真实世界的传感器数据。我需要这些数据来创建我的测试。我尝试了以下两种方法都没有成功。
我真的被这个问题难住了,因为通常 SQLiteOpenHelper
可以完美地加载 /data/data/packageName/databases/
中的任何数据库。
我试过了android-sqlite-asset-helper:
val targetContext by lazy { InstrumentationRegistry.getTargetContext() }
val testContext by lazy { InstrumentationRegistry.getContext() }
const val TEST_DB_NAME = "testdb.sqlite"
const val VERSION = 1018
class TestDatabase(context: Context) :
SQLiteAssetHelper(context, TEST_DB_NAME, null, null, VERSION) {
...
}
但是 none 的上下文有效。使用 testContext
无法将数据库写入文件系统,使用 targetContext
则无法访问 androidTest/assets/databases/testdb.sqlite
.
当我尝试手动复制 () 时:
const val DB_PATH = "/data/data/de.leo.smartTrigger/databases/"
@Throws(IOException::class)
private fun copyDatabase(testContext: Context) {
val inputStream = testContext.getAssets().open("databases/$TEST_DB_NAME")
val outFileName = DB_PATH + TEST_DB_NAME
val outputStream = FileOutputStream(outFileName)
val buffer = ByteArray(1024)
var length: Int = inputStream.read(buffer)
while (length > 0) {
outputStream.write(buffer, 0, length)
length = inputStream.read(buffer)
}
outputStream.flush()
outputStream.close()
inputStream.close()
}
//after
copyDatabase(testContext)
val db = SQLiteDatabase.openDatabase(DB_PATH + TEST_DB_NAME, null, SQLiteDatabase.CREATE_IF_NECESSARY)
//yields an empty database although
File(DB_PATH + TEST_DB_NAME).exists() == true // true
如何从 androidTest/assets/databases/testdb.sqlite
加载数据库? in-memory的加分项,因为反正我考完都会被丢弃
我找到了解决方案:
Convert the database to input-statements
sqlite testdb.sqlite .dump > testdb.sql
将此文件放入 androidTest/assets/databases/
然后创建数据库:
class MyDatabaseOpenHelper(val context: Context,
version: Int = 1) : SQLiteOpenHelper
(context,
null,
null,
version,
null) {
override fun onCreate(db: SQLiteDatabase?) {
BufferedReader(InputStreamReader(context.getAssets().open("databases/testdb.sql"))).apply {
lines().forEach {
try {
db!!.execSQL(it)
} catch (e: SQLiteException) {
Log.w("read test db", e)
}
}
close()
}
}
override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
//noop load from file
}
}
通过不提供名称,我们从 sql 语句创建了一个内存数据库。
这个解决方案并不完美,因为它需要在更新测试数据库时手动执行步骤,但它对我有用。
对于我的单元测试,我在 SQLite 数据库中收集了真实世界的传感器数据。我需要这些数据来创建我的测试。我尝试了以下两种方法都没有成功。
我真的被这个问题难住了,因为通常 SQLiteOpenHelper
可以完美地加载 /data/data/packageName/databases/
中的任何数据库。
我试过了android-sqlite-asset-helper:
val targetContext by lazy { InstrumentationRegistry.getTargetContext() }
val testContext by lazy { InstrumentationRegistry.getContext() }
const val TEST_DB_NAME = "testdb.sqlite"
const val VERSION = 1018
class TestDatabase(context: Context) :
SQLiteAssetHelper(context, TEST_DB_NAME, null, null, VERSION) {
...
}
但是 none 的上下文有效。使用 testContext
无法将数据库写入文件系统,使用 targetContext
则无法访问 androidTest/assets/databases/testdb.sqlite
.
当我尝试手动复制 (
const val DB_PATH = "/data/data/de.leo.smartTrigger/databases/"
@Throws(IOException::class)
private fun copyDatabase(testContext: Context) {
val inputStream = testContext.getAssets().open("databases/$TEST_DB_NAME")
val outFileName = DB_PATH + TEST_DB_NAME
val outputStream = FileOutputStream(outFileName)
val buffer = ByteArray(1024)
var length: Int = inputStream.read(buffer)
while (length > 0) {
outputStream.write(buffer, 0, length)
length = inputStream.read(buffer)
}
outputStream.flush()
outputStream.close()
inputStream.close()
}
//after
copyDatabase(testContext)
val db = SQLiteDatabase.openDatabase(DB_PATH + TEST_DB_NAME, null, SQLiteDatabase.CREATE_IF_NECESSARY)
//yields an empty database although
File(DB_PATH + TEST_DB_NAME).exists() == true // true
如何从 androidTest/assets/databases/testdb.sqlite
加载数据库? in-memory的加分项,因为反正我考完都会被丢弃
我找到了解决方案:
Convert the database to input-statements
sqlite testdb.sqlite .dump > testdb.sql
将此文件放入 androidTest/assets/databases/
然后创建数据库:
class MyDatabaseOpenHelper(val context: Context,
version: Int = 1) : SQLiteOpenHelper
(context,
null,
null,
version,
null) {
override fun onCreate(db: SQLiteDatabase?) {
BufferedReader(InputStreamReader(context.getAssets().open("databases/testdb.sql"))).apply {
lines().forEach {
try {
db!!.execSQL(it)
} catch (e: SQLiteException) {
Log.w("read test db", e)
}
}
close()
}
}
override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
//noop load from file
}
}
通过不提供名称,我们从 sql 语句创建了一个内存数据库。
这个解决方案并不完美,因为它需要在更新测试数据库时手动执行步骤,但它对我有用。