Sqldelight无法创建数据库表,测试提示无LocalMember表
使用SqlDelight实现本地数据持久化时,运行测试出现以下错误:
org.sqlite.SQLiteException: [SQLITE_ERROR] SQL error or missing database (no such table: LocalMember)
此前功能运行正常,新建一个无其他依赖的测试项目后仍出现相同错误。相关代码及配置如下:
测试代码
class LocalDataTest { private lateinit var db: database private lateinit var localData: LocalData @BeforeEach fun setUp() { val driver: SqlDriver = JdbcSqliteDriver(JdbcSqliteDriver.IN_MEMORY) //实际项目用文件DB+Koin注入,同样报错 database.Schema.create(driver) db = database(driver) localData = LocalData(db) } @Test fun addMember() { runBlocking { localData.addMember(LocalMember("1", "test")) val member = db.dataQueries.selectAll().executeAsOne() assertEquals("test", member.name) } } }
SqlDelight SQL文件
CREATE TABLE IF NOT EXISTS LocalMember ( id TEXT PRIMARY KEY, name TEXT NOT NULL ); selectAll: SELECT * FROM LocalMember; upsert: -- Insert or ignore the record INSERT OR IGNORE INTO LocalMember (id, name) VALUES (?, ?); -- Then update the record assuming it exists UPDATE LocalMember SET name = COALESCE(?, name) WHERE id = ?;
settings.gradle.kts
pluginManagement { repositories { gradlePluginPortal() maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") mavenCentral() } plugins { kotlin("jvm").version(extra["kotlin.version"] as String) kotlin("plugin.serialization").version(extra["kotlin.version"] as String) id("org.jetbrains.compose").version(extra["compose.version"] as String) id("app.cash.sqldelight").version("2.0.0") apply false } }
build.gradle.kts
dependencies { implementation("app.cash.sqldelight:sqlite-driver:2.0.0") } sqldelight { databases { create("database") { packageName.set("com.ayitinya.data") generateAsync.set(true) } } }
检查SQL文件存放路径
SqlDelight要求SQL文件必须放在src/main/sqldelight/[packageName]或src/test/sqldelight/[packageName]目录下,对应你设置的packageName.set("com.ayitinya.data"),路径应该是src/main/sqldelight/com/ayitinya/data(测试场景用src/test下的对应路径)。如果文件放错位置,Schema生成时不会包含该表,直接导致测试时找不到表。适配异步生成配置
你在配置里开了generateAsync.set(true),这会生成协程异步API,但测试里直接调用的executeAsOne()是同步方法,容易出现线程或API不匹配问题。要么把generateAsync改成false,要么用异步版本的API:val member = db.dataQueries.selectAll().executeAsOneAsync().await()验证Schema生成结果
去build/generated/sqldelight目录下查看自动生成的代码,确认database.Schema里包含LocalMember表的创建语句。如果没有,先执行./gradlew clean build --refresh-dependencies清理缓存并重新构建,再检查生成结果。确认测试数据库初始化成功
对于内存数据库,可以在Schema创建后加验证代码,确保表确实被创建:val result = driver.executeQuery(null, "SELECT name FROM sqlite_master WHERE type='table' AND name='LocalMember';", 0) assert(result.next()) { "LocalMember表未创建成功" }排查SQL语法兼容性
虽然你的SQL看起来没问题,但SqlDelight对语法细节要求严格,比如语句分隔、注释格式。可以先简化SQL文件,只保留CREATE TABLE语句测试,确认表能正常创建后,再逐步添加查询和upsert语句。
内容的提问来源于stack exchange,提问作者ayitinya

