我想知道如何在 KMM 上为 SQLDelight 编写单元测试。首先,我什至无法正确添加 SQLDelight 依赖项。
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
// SQLDelight tests
implementation("com.squareup.sqldelight:sqlite-driver:1.4.3")
}
}
在我添加依赖项然后同步项目后,该项目甚至没有构建。有人可以告诉我这是否是添加 sqlite 驱动程序依赖项的正确方法?
任何帮助将不胜感激!
答案 0 :(得分:3)
您可以在 KaMPKit 中看到一个基本示例。
如果您在非测试代码中配置了 sqldelight,则不需要在 commonTest
中依赖它自己的驱动程序。
在我们的测试代码中,我们有一个 expect
为测试创建数据库连接。
internal expect fun testDbConnection(): SqlDriver
然后在 iOS 和 Android 代码中,actual
定义。
依赖配置看起来(大致)是这样的:
commonMain {
implementation("com.squareup.sqldelight:runtime:1.4.4")
}
androidMain {
implementation("com.squareup.sqldelight:android-driver:1.4.4")
}
iosMain {
implementation("com.squareup.sqldelight:native-driver:1.4.4")
}
有了这个,您应该能够编写 sqldelight 测试。
答案 1 :(得分:0)
感谢您的回答!我遇到了另一个问题。 “预期的函数‘createDriver’在 JVM 模块 KMM.shared(测试)中没有实际声明”。在 KaMPKit 项目中,我没有找到任何与 JVM 相关的内容。
Getting Started on JVM with SQLite 包含必要的说明。
你需要添加一个依赖
dependencies {
implementation "com.squareup.sqldelight:sqlite-driver:1.5.0"
}
进入你的“jvmMain”源集,接下来在你的“jvmMain”模块中实现真正有趣的createDriver。
我感谢 Kevin 的回答,并补充说使用 SqlDeLite 的测试应该放在平台模块(“androidTest”和“iosTest”)中,而不是放在“commonTest”中。
您需要向您的 SUT 提供实际驱动程序的实现,使用应用上下文。 对于单元测试,您需要替换上下文,例如查看 Robolectric。
添加依赖
dependencies {
implementation("org.robolectric:robolectric:4.4")
}
进入“androidTest”sourceSet(不知道iOS可以用什么),获取应用上下文:
val context = ApplicationProvider.getApplicationContext<Context>()
并使用它来获取驱动程序的平台实现:
val driver = DatabaseDriverFactory(context).createDriver(Database.Schema, "test.db")
答案 2 :(得分:0)
我在使用 Context 进行测试时遇到问题,发现使用内存数据库会更快。这样做的另一个好处是不需要用于测试的设备。
我的做法:
val androidTest by getting {
dependencies {
// ...
implementation("com.squareup.sqldelight:sqlite-driver:1.4.4")
}
}
internal expect fun createTestSqlDriver(): SqlDriver
internal actual fun createTestSqlDriver(): SqlDriver {
return JdbcSqliteDriver(JdbcSqliteDriver.IN_MEMORY).apply {
MyDatabase.Schema.create(this)
}
}
internal class MyClassDbTests {
private val sqlDriver = createTestSqlDriver()
private val calendarDb = MyDatabase(sqlDriver)
fun insert_addItems_verifyCorrectNumOfItemsInDb() {
// GIVEN
val myQueries = myDatabase.mydbQueries
myQueries.deleteAllEvents()
val numItemsBeforeInsertion = myQueries.selectAll().executeAsList().size
// WHEN
myQueries.insertItem(1, 2, 3)
myQueries.insertItem(10, 20, 30)
val numItemsAfterInsertion = myQueries.selectAll().executeAsList().size
// THEN
assertEquals(0, numItemsBeforeInsertion)
assertEquals(2, numItemsAfterInsertion)
}
}
我发现以下帖子很有用:
答案 3 :(得分:0)
示例
package com.viki.vikilitics_kmm
import com.squareup.sqldelight.sqlite.driver.JdbcDriver
import com.google.common.truth.Truth.assertThat
import com.squareup.sqldelight.db.SqlDriver
import com.squareup.sqldelight.sqlite.driver.JdbcSqliteDriver
import com.viki.vikiliticskmm.Event
import com.viki.vikiliticskmm.EventQueries
import org.junit.After
import org.junit.Before
import org.junit.Test
import java.sql.DriverManager
import java.sql.Connection
class AndroidEventDatabaseTest {
private lateinit var queries: EventQueries
// When your test needs a driver
@Before
fun before() {
val driver = JdbcSqliteDriver(JdbcSqliteDriver.IN_MEMORY)
val database = EventDatabase(driver)
EventDatabase.Schema.create(driver)
queries = database.eventQueries
}
@Test
fun `select all events`() {
queries.insertEvent("1", "2", "{Click,Open}")
queries.insertEvent("2", "2", "{Click,Close}")
assertThat(queries.selectAllEvents().executeAsList())
.containsExactly(
Event(
as_counter = "1",
t_ms = "2",
event_map = "{Click,Open}"
),
Event(
as_counter = "2",
t_ms = "2",
event_map = "{Click,Close}"
)
)
}
@Test
fun `delete multiple events`() {
queries.insertEvent("1", "1", "{Click,Open}")
queries.insertEvent("1", "2", "{Click,Close},{Read,Open}")
queries.insertEvent("1", "3", "{Click,Open}")
queries.insertEvent("2", "3", "{Click,Open}")
val event1 = listOf("1","3")
val event2 = listOf("1","2")
val event3 = listOf("1","4")
val eventList = listOf(event1,event2,event3)
for (event in eventList){
queries.deleteEventListByKey(event.elementAt(0), event.elementAt(1))
}
assertThat(queries.selectAllEvents().executeAsList())
.containsExactly(
Event(
as_counter = "1",
t_ms = "1",
event_map = "{Click,Open}"
), Event(
as_counter = "2",
t_ms = "3",
event_map = "{Click,Open}"
),
)
}
@Test
fun `delete single event`() {
queries.insertEvent("1", "1", "{Click,Open}")
queries.insertEvent("1", "2", "{Click,Close},{Read,Open}")
queries.insertEvent("1", "3", "{Click,Open}")
queries.insertEvent("2", "3", "{Click,Open}")
queries.deleteEventListByKey("1", "3")
assertThat(queries.selectAllEvents().executeAsList())
.containsExactly(
Event(
as_counter = "1",
t_ms = "1",
event_map = "{Click,Open}"
), Event(
as_counter = "2",
t_ms = "3",
event_map = "{Click,Open}"
),
Event(
as_counter = "1",
t_ms = "2",
event_map = "{Click,Close},{Read,Open}"
)
)
}
@Test
fun `update events`() {
queries.insertEvent("1", "2", "{Click,Open}")
queries.insertEvent("1", "2", "{Click,Close}")
assertThat(queries.selectAllEvents().executeAsList())
.containsExactly(
Event(
as_counter = "1",
t_ms = "2",
event_map = "{Click,Close}"
)
)
}
}