Meh*_*sly 4 java unit-testing dependency-injection kotlin ktor
该文档讨论了依赖注入,但并没有真正展示它是如何完成的.
文档也没有完成,并有一堆占位符:http: //ktor.io/getting-started.html
我尝试以接受参数(这是我的依赖)的方式创建我的main函数,但是当我调用时在测试端失败了withTestApplication
.我查看了应用程序代码,发现Application接受了一个配置对象,但我不知道如何更改该配置对象以在其中注入一些依赖项.
package org.jetbrains.ktor.application
/**
* Represents configured and running web application, capable of handling requests
*/
class Application(val environment: ApplicationEnvironment) : ApplicationCallPipeline() {
/**
* Called by host when [Application] is terminated
*/
fun dispose() {
uninstallAllFeatures()
}
}
/**
* Convenience property to access log from application
*/
val Application.log get() = environment.log
Run Code Online (Sandbox Code Playgroud)
在测试代码中使用withTestApplication
我有类似于下面的内容:
@Test
internal fun myTest() = withTestApplication (Application::myMain)
Run Code Online (Sandbox Code Playgroud)
withTestApplication
如果我myMain
使用参数调用(我需要模拟和注入的参数),上述操作将失败.
更新:
问题是,在我的请求处理,我使用一个连接到外部的其他网络服务,并做了一些要求,我需要一种方法,以便能够在我的测试,以便注入这个我可以存根/模拟它,改变依赖类的基于我的测试用例的行为.
Koin 的简单示例
1) 首先,定义我们的 prod 和 test 依赖项:
val prodModule = module {
single<IFirstService> { RealFirstService() }
single<ISecondService> { RealSecondService() }
}
val testModule = module {
single<IFirstService> { FakeFirstService() }
single<ISecondService> { FakeSecondService() }
}
Run Code Online (Sandbox Code Playgroud)
2)然后在app启动前添加DI初始化:
fun main(args: Array<String>) {
startKoin(listOf(prodModule))
embeddedServer(Netty, commandLineEnvironment(args)).start(true)
}
Run Code Online (Sandbox Code Playgroud)
3)在应用程序或路由中使用注入:
fun Application.apiModule() {
val firstService: IFirstService by inject()
val secondService: ISecondService by inject()
...
routing {
someApi(inject(), inject())
}
}
Run Code Online (Sandbox Code Playgroud)
4)(可选)对于测试,只需在运行测试之前在 testModule 中添加初始化:
fun testApp(test: TestApplicationEngine.() -> Unit) {
withTestApplication({
... // configure your test app here
stopKoin() // Need to stop koin and restart after other tests
startKoin(listOf(testModule)) // Init with test DI
apiModule() // Run you application
})
}
// And run tests
@Test
fun `get events`() = testApp {
// do tests
}
Run Code Online (Sandbox Code Playgroud)
就这样!
Ktor没有内置的依赖注入机制.如果您需要使用DI,则需要使用您喜欢的任何框架,例如Guice.它看起来像这样:
fun Application.module() {
Guice.createInjector(MainModule(this))
}
// Main module, binds application and routes
class MainModule(private val application: Application) : AbstractModule() {
override fun configure() {
bind(Application::class.java).toInstance(application)
... other bindings ...
}
}
Run Code Online (Sandbox Code Playgroud)
这样您就可以将应用程序组合委托给Guice并将其构建为任何其他应用程序.例如,您可以组合应用程序的不同部分,如下所示:
class Hello @Inject constructor(application: Application) {
init {
application.routing {
get("/") {
call.respondText("Hello")
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后将其绑定在主模块中:
bind(Hello::class.java).asEagerSingleton()
Run Code Online (Sandbox Code Playgroud)
asEagerSingleton
是必要的,以便Guice将热切地创建它,因为没有其他服务会查询它.
归档时间: |
|
查看次数: |
1863 次 |
最近记录: |