ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

SQLDelight 在 Android 测试中用 JdbcSqliteDriver 脱离模拟器验证数据库与迁移

SQLDelight 在 Android 测试中用 JdbcSqliteDriver 脱离模拟器验证数据库与迁移 后端ORM【免费下载链接】sqldelightSQLDelight - Generates typesafe Kotlin APIs from SQL项目地址https://gitcode.com/gh_mirrors/sq/sqldelight点击查看免费下载本文面向使用 SQLDelight 的 Android 开发者讲解如何在 JVM 单元测试中引入app.cash.sqldelight:sqlite-driver用JdbcSqliteDriver替代 Android 平台驱动从而在没有模拟器、没有真机的情况下完成数据库建表、查询与迁移逻辑的验证。读完本文你将掌握测试依赖的配置方式、内存/临时数据库的初始化套路、迁移验证的 schema 传入方式以及如何让 JVM 端的 SQLite 版本与 Android 内建版本保持一致。为什么要在 Android 测试中替换驱动SQLDelight 在 Android 平台默认使用 AndroidSqliteDriver位于drivers/android-driver它通过androidx.sqlite的SupportSQLiteOpenHelper与框架层 SQLite 交互。这类测试依赖 Android 运行时环境通常需要在模拟器或真机上执行启动慢、不稳定、CI 成本高。在验证迁移.sqm文件或纯粹校验数据库层行为时数据库语义本身与平台无关因此完全可以把驱动换成基于 JDBC 的 JVM 实现JdbcSqliteDriver让同一套Database、Database.Schema与生成的查询 API 直接跑在本地 JVM 上。JdbcSqliteDriver是 SQLDelight 官方提供的 JVM SQLite 驱动POM_DESCRIPTIONJVM SQLite driver for SQLDelight与 Android 驱动实现的是同一套SqlDriver接口所以业务代码、schema 与迁移脚本都可以无缝复用测试代码只需在初始化处换一行驱动即可。添加测试依赖Kotlin DSL 与 Groovy 两种写法原文档给出的依赖坐标是app.cash.sqldelight:sqlite-driver需要放在testImplementation而非implementation作用域确保驱动只参与 JVM 单元测试编译与运行不会打进 APK// build.gradle.ktsKotlin DSL dependencies { testImplementation(app.cash.sqldelight:sqlite-driver:版本号) }// build.gradleGroovy DSL dependencies { testImplementation app.cash.sqldelight:sqlite-driver:版本号 }其中版本号需要替换为你实际使用的 SQLDelight 版本原文档以{{ versions.sqldelight }}占位。该驱动模块内部依赖org.xerial:sqlite-jdbc仓库 gradle/libs.versions.toml 中将其默认版本声明为3.53.4.0sqliteJdbc { module org.xerial:sqlite-jdbc, version 3.53.4.0 }实际生效版本以你的依赖解析结果为准。由于依赖声明在testImplementationRobolectric 或纯 JUnit 测试都能直接运行无需任何 Android 设备。初始化驱动内存库 Schema 创建依赖就绪后测试中只需要两步构造JdbcSqliteDriver然后调用Database.Schema.create(driver)建表private lateinit var driver: JdbcSqliteDriver Before fun before() { driver JdbcSqliteDriver(JdbcSqliteDriver.IN_MEMORY) Database.Schema.create(driver) }JdbcSqliteDriver.IN_MEMORY是驱动内置的常量源码中定义在 JdbcSqliteDriver.kt 的 companion object 中companion object { const val IN_MEMORY jdbc:sqlite: }需要留意一个容易误读的细节IN_MEMORY的值是jdbc:sqlite:空路径根据驱动源码中的 KDocjdbc:sqlite:会创建一个临时数据库临时文件在连接关闭时被删除而jdbc:sqlite::memory:才是严格的纯内存数据库。因此IN_MEMORY更准确的理解是用完即弃的临时库对单元测试来说效果等价且足够干净。Database.Schema.create(driver)执行的是 SQLDelight 编译器生成的建表脚本对应你的.sq/.sqm文件这一步保证了后续查询测试能在真实 schema 上运行而不是空库。源码佐证驱动的 URL 形态与连接管理JdbcSqliteDriver的构造器接收 JDBC 连接串源码 KDoc 完整列举了支持的形态jdbc:sqlite:/path/to/myDatabase.db—— 文件数据库改动写入文件系统jdbc:sqlite:—— 临时数据库连接关闭即删除临时文件即IN_MEMORYjdbc:sqlite::memory:—— 纯内存数据库jdbc:sqlite:file:memdb1?modememorycacheshared—— 可跨连接共享的具名内存库。驱动内部通过connectionManager(url, properties)按路径自动选择连接管理策略见 JdbcSqliteDriver.kt空路径、:memory:、file::memory:、:resource:前缀或 URL 含modememory时走StaticConnectionManager整个驱动复用一个连接close()时关闭连接其余文件数据库走ThreadedConnectionManager每个线程通过ThreadLocal持有独立连接连接必须在打开的线程上关闭事务结束后自动归还。对于单线程的单元测试IN_MEMORY对应的StaticConnectionManager足够简单可靠。事务底层通过BEGIN TRANSACTION/END TRANSACTION/ROLLBACK TRANSACTION三条原生语句实现行为与 Android 端一致。迁移验证把 Schema 直接传给构造器原文档开篇提到像迁移验证这类测试这是替换驱动的典型场景。SQLDelight 的.sqm迁移文件在编译期会生成Database.Schema.migrate(...)逻辑。JVM 驱动对此提供了专门的重载构造器定义在 JdbcSqliteSchema.ktfun JdbcSqliteDriver( url: String, properties: Properties Properties(), schema: SqlSchemaQueryResult.ValueUnit, migrateEmptySchema: Boolean false, vararg callbacks: AfterVersion, ): JdbcSqliteDriver其内部逻辑为通过PRAGMA user_version读取当前库版本若版本为 0 且migrateEmptySchema false默认调用schema.create(driver)建库并写入schema.version若版本小于schema.version调用schema.migrate(driver, version, schema.version, *callbacks)执行迁移并更新user_version。也就是说迁移测试只需要把Database.Schema传入构造器val driver JdbcSqliteDriver( JdbcSqliteDriver.IN_MEMORY, Properties(), Database.Schema, )驱动会在事务中自动完成建库或迁移无需手动调用create。vararg callbacks: AfterVersion还支持在迁移到指定版本后执行回调对应AfterVersion可以用于断言迁移中间态。更完整的迁移主题可参考 docs/jvm_sqlite/migrations.md。对齐 Android 内建 SQLite 版本Android 系统内建 SQLite 的版本由设备的 API level 决定通常低于最新版如果你的测试想模拟真机上的 SQLite 行为例如验证某些仅在旧版本上成立的 SQL 语义可以覆盖sqlite-jdbc的版本使其与目标 Android 版本的 SQLite 一致。原文档给出的示例是Android API 23 内建 SQLite 3.8.10.2则做如下覆盖dependencies { testImplementation(org.xerial:sqlite-jdbc) { // 覆盖 sqlite-driver 使用的 sqlite 版本以匹配 Android API 23 version { strictly(3.8.10.2) } } }要点说明坐标不写版本号让 Gradle 解析由sqlite-driver传递进来的默认版本再用version { strictly(...) }强制固定为指定版本避免依赖升级悄悄改变测试环境需要同时声明testImplementation(app.cash.sqldelight:sqlite-driver:...)覆盖语句只是调整传递依赖的解析结果目标版本需要与你关心的 Android 版本内建 SQLite 对应org.xerial:sqlite-jdbc的发布版本号与 SQLite C 库版本对应如 3.8.10.2仓库当前默认的sqlite-jdbc为 3.53.4.0其语义更接近新版本 SQLite如需模拟旧设备行为必须显式覆盖。如果你使用 Kotlin DSL等价写法为testImplementation(org.xerial:sqlite-jdbc) { version { strictly(3.8.10.2) } }进阶实践磁盘文件库与驱动自测参考除了内存库JdbcSqliteDriver也支持指向真实文件的连接串如jdbc:sqlite:test.db见 docs/jvm_sqlite/index.md适合需要验证落盘行为、重启后数据持久化的测试这类场景下连接走ThreadedConnectionManager多线程并发测试时注意各线程连接是独立的。驱动自身的测试文件也可以作为使用范例仓库 drivers/sqlite-driver/src/test/kotlin/com/squareup/sqldelight/driver/sqlite/ 下的SqliteDriverTest.kt、SqliteQueryTest.kt、SqliteTransacterTest.kt均以JdbcSqliteDriver(IN_MEMORY)起步覆盖了查询、事务与驱动基础行为SqliteEphemeralTest.kt则展示了jdbc:sqlite:$suffix临时库的另一种构造方式。这些测试与 drivers/driver-test 中的跨驱动通用测试套件互为印证说明JdbcSqliteDriver与 Android 驱动在行为层面保持了一致。小结将 Android 测试中的数据库验证迁移到 JVM只需三步在testImplementation加入app.cash.sqldelight:sqlite-driver用JdbcSqliteDriver(JdbcSqliteDriver.IN_MEMORY)初始化内存/临时库对迁移场景把Database.Schema传入驱动构造器自动建库或迁移。必要时通过strictly覆盖sqlite-jdbc版本以对齐目标 Android 版本的内建 SQLite。这套方案让数据库相关测试完全摆脱模拟器与真机跑得更快、更稳定且与 Android 环境下的真实驱动保持语义一致。赞分享后端ORM【免费下载链接】sqldelightSQLDelight - Generates typesafe Kotlin APIs from SQL项目地址https://gitcode.com/gh_mirrors/sq/sqldelight点击查看免费下载相关推荐VirtualApp数据库迁移测试验证迁移正确性VirtualApp数据库迁移测试验证迁移正确性 在移动应用开发中数据库迁移是确保数据一致性和应用稳定性的关键环节。VirtualApp简称VA作为一款移动开发虚拟化WRF模型高级应用区域气候模拟与极端天气预测案例WRF模型高级应用区域气候模拟与极端天气预测案例 Weather Research and Forecasting WRF 模型是一款被广泛应用的中尺度气象数GLM-5.3的网络安全能力有多强CyberGym 84.5分背后的开源SOTA漏洞发现GLM 5.3的网络安全能力有多强CyberGym 84.5分背后的开源SOTA漏洞发现 GLM 5.3 是智谱AI开源的大语言模型与 GLM 5.2 共用后端ORM上一篇WebPlotDigitizer5分钟从科研图表中提取数据的免费神器下一篇别再一格一格摆方块了Arnis 把真实城市生成进 Minecraft 的完整教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表