将 koin 数据库注入 ktor 测试应用程序

问题描述 投票:0回答:1

我的应用程序设置为在服务器开始运行时立即加载数据库 与

createdAtStart = true

val dbModule = module {
    single(createdAtStart = true) {
        Db(
            driverClassName = "org.h2.Driver", jdbcURL = "jdbc:h2:file:./build/db"
        )
    }

正常运行服务器时,我不需要在任何地方手动注入数据库来初始化它,因为它是自动完成的并且依赖于数据库对象获取

此外,用于测试的数据库是内存数据库,可以使用 koin 轻松注入单元测试

factory(qualifier = named("test")) { params ->
        Db(
            driverClassName = "org.h2.Driver",
            jdbcURL = "jdbc:h2:mem:${params.get<String>()};DB_CLOSE_DELAY=-1"
        )
    }

问题

在测试整个应用程序时,即使用 ktor 的服务器路由

testApplication
,默认数据库是直接注入的,我无法注入测试数据库。

// test is empty because i realised i can't inject my test db
class ApplicationTest: KoinTest {


    @Test
    fun testRoot() = testApplication {



        val response = client.get("/")
        assertEquals(HttpStatusCode.OK, response.status)
    }
}

我认为我的应用程序设计和文件结构存在缺陷,因为这是我第一次使用 ktor

如何将正确的数据库放入测试应用程序

kotlin dependency-injection ktor koin
1个回答
0
投票

我必须稍微重组我的代码库。

主数据库不再提前创建

// koin.kt
val dbModule = module {
    single {
        Db(
            driverClassName = "org.h2.Driver", jdbcURL = "jdbc:h2:file:./build/db"
        )
    }

    factory(qualifier = named("test")) { params ->
        Db(
            driverClassName = "org.h2.Driver",
            jdbcURL = "jdbc:h2:mem:${params.get<String>()};DB_CLOSE_DELAY=-1"
        )
    }
}

依赖注入和数据库配置被分成不同的模块,并基于主模块上的测试标志来使用

// application.kt

fun Application.di() {
    install(Koin) {
        slf4jLogger()
        modules(dbModule)
    }
}

fun Application.configureDb() {
    val db: Db by inject()
    TransactionManager.defaultDatabase = db.database // this line isn't really need as exposed uses last open db connection
}

fun Application.main(testing: Boolean = false) {
    if (!testing) {
        di()
        configured()
    }
}

class ApplicationTest : KoinTest {
    private lateinit var db: Db

    @BeforeEach
    fun `setup db`() {
        db = get {
            parametersOf("")
        }

        TransactionManager.defaultDatabase = db.database
    }

    @Test
    fun testRoot() = testApplication {

        application {
            module(testing = true)
        }

        environment {
            config =
                ApplicationConfig("test_application.yaml") // loads environment variables for test


        val response = client. Get("/")
        assertEquals(HttpStatusCode.OK, response.status)
    }

    companion object {
        @JvmStatic
        @BeforeAll
        fun `start koin`(): Unit {
            startKoin {
                modules(dbModule)
            }
        }
    }
}

请参阅这些链接以获取有关所使用的某些方法的更多说明

如何使用

testApplication()
在Ktor中设置Koin?

为ktor配置测试环境

youtrack 问题

© www.soinside.com 2019 - 2024. All rights reserved.