環境
ktor_version=1.4.1
kotlin_version=1.4.10
koin_version=2.1.6
joda-time_version=2.10.8
解説
細かい解説はコードコメントにて。
現在日時を差し替える
以下のように現在日時をつぶやくクラスがいたとする
class ClockSpeaker(private val clock: Clock) {
fun speak(): String {
return clock.now().toString("yyyy年MM月dd日のHH:mm:ssやでー")
}
}
テストしやすいようにClockというinterfaceを定義し、そこから日時を取得する。
テスト用に指定日時を返す実装も作っておく。
import org.joda.time.DateTime
/**
* 現在日時を取得するためのinterface
*/
interface Clock {
fun now(): DateTime
}
/**
* 現在日時を取得する
*/
class ClockNow : Clock {
override fun now(): DateTime {
return DateTime()
}
}
/**
* 指定された日時を取得する
*/
class ClockSpecify(private val specifyDateTime: DateTime) : Clock {
override fun now(): DateTime {
return specifyDateTime
}
}
ルーティングなどはこんな感じになる
import io.ktor.application.*
import io.ktor.http.*
import io.ktor.response.*
import io.ktor.routing.*
import org.koin.core.module.Module
import org.koin.dsl.module
import org.koin.ktor.ext.Koin
import org.koin.ktor.ext.inject
fun main(args: Array<String>): Unit = io.ktor.server.netty.EngineMain.main(args)
@Suppress("unused") // Referenced in application.conf
@kotlin.jvm.JvmOverloads
fun Application.module(testing: Boolean = false, testModule: Module? = null) { //testModule: Module? = nullという引数を追加
install(Koin) {
modules(getModule())
if (testing && testModule != null) {
//テスト用のModuleで上書き
modules(testModule)
}
}
routing {
val speaker by inject<ClockSpeaker>() // インスタンスの取得
get("/") {
call.respondText("HELLO WORLD!" + speaker.speak(), contentType = ContentType.Text.Plain)
}
}
}
fun getModule(): Module {
return module {
factory { ClockNow() as Clock }
factory { ClockSpeaker(get()) as ClockSpeaker }
}
}
ここまでは通常のKoinの使用と変わらず。
続いてテストコード。
import io.ktor.http.*
import io.ktor.server.testing.*
import org.joda.time.DateTime
import kotlin.test.Test
import kotlin.test.assertEquals
class ApplicationTest {
@Test
fun testRoot() {
withTestApplication({
val now = DateTime(2020, 11, 29, 12, 23, 34)
val testModule = org.koin.dsl.module(override = true) { // override = trueで上書きができる
factory { ClockSpecify(now) as Clock }
}
module(testing = true, testModule = testModule)
}) {
handleRequest(HttpMethod.Get, "/").apply {
assertEquals(HttpStatusCode.OK, response.status())
assertEquals("HELLO WORLD!2020年11月29日の12:23:34やでー", response.content)
}
}
}
}
たぶんコレが一番シンプルなはず…。