LoginSignup
1
0

More than 3 years have passed since last update.

Ktor + Koinでテスト時にインスタンスを差し替える

Posted at

環境

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

たぶんコレが一番シンプルなはず…。

コード全体

iwahara/KoinTestExample: Koinを使ってテストのときだけインスタンスを差し替えるサンプル

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0