【问题标题】:How to Write Unit Tests for SQLDelight on KMM如何在 KMM 上为 SQLDelight 编写单元测试
【发布时间】:2021-04-16 04:38:51
【问题描述】:

我想知道如何在 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 驱动程序依赖项的正确方法吗?

任何帮助将不胜感激!

【问题讨论】:

    标签: unit-testing kotlin-multiplatform sqldelight kotlin-multiplatform-mobile


    【解决方案1】:

    您可以在KaMPKit 中看到一个基本示例。

    如果您在非测试代码中配置了 sqldelight,则不需要在 commonTest 中对它自己的驱动程序依赖。

    在我们的测试代码中,我们有一个 expect 来创建用于测试的数据库连接。

    internal expect fun testDbConnection(): SqlDriver
    

    然后在iOSAndroid 代码中,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 测试了。

    【讨论】:

    • 感谢您的回答!我遇到了另一个问题。 “预期的函数‘createDriver’在 JVM 的模块 KMM.shared (test) 中没有实际声明”。在 KaMPKit 项目中,我没有找到任何与 JVM 相关的内容。
    【解决方案2】:

    我在使用 Context 进行测试时遇到问题,发现使用内存数据库更快。这还具有不需要设备进行测试的好处。

    我的做法:

    1. 将 JdbcSqliteDriver 添加到 androidTest 源集(“共享”下的 build.gradle)
    val androidTest by getting {
        dependencies {
            // ...
            implementation("com.squareup.sqldelight:sqlite-driver:1.4.4")
        }
    }
    
    1. 添加期望/实际函数来创建驱动程序:
    • 在“commonTest”目录下的文件中(例如 createTestSqlDriver.kt)

    internal expect fun createTestSqlDriver(): SqlDriver

    • 在“androidTest”下的文件中
    internal actual fun createTestSqlDriver(): SqlDriver {
        return JdbcSqliteDriver(JdbcSqliteDriver.IN_MEMORY).apply {
            MyDatabase.Schema.create(this)
        }
    }
    
    1. 现在我可以在“commonTest”下的测试中创建和使用数据库。比如:
    internal class MyClassDbTests {
    
        private val sqlDriver = createTestSqlDriver()
        private val myDatabase = 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)
        }
    }
    

    我发现以下帖子很有用:

    【讨论】:

    • 用这个IN_MEMORY测试更快
    【解决方案3】:

    感谢您的回答!我遇到了另一个问题。 “预期的函数‘createDriver’在 JVM 的模块 KMM.shared (test) 中没有实际声明”。在 KaMPKit 项目中,我没有找到任何与 JVM 相关的内容。

    Getting Started on JVM with SQLite 包含必要的说明。

    你需要添加一个依赖

    dependencies {
      implementation "com.squareup.sqldelight:sqlite-driver:1.5.0"
    }
    

    进入你的“jvmMain”sourceSet,接下来在你的“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")
    

    【讨论】:

      【解决方案4】:

      例子

      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}"
                      )
                  )
      
      
          }
      
      }
      

      参考资料 https://github.com/touchlab/KaMPKit/blob/main/shared/src/commonTest/kotlin/co/touchlab/kampkit/SqlDelightTest.kt

      【讨论】:

        猜你喜欢
        • 2018-01-17
        • 2012-01-06
        • 2019-03-17
        • 2016-04-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多