KotlinTest с Koin: InvocationTargetException - PullRequest
1 голос
/ 05 февраля 2020

Я не могу использовать Koin 2.0.1 с Kotlin -test 3.4.2. Я получаю InvocationTargetException, как это:

Running koinexample.KoinSampleTests
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.009 sec <<< FAILURE! - in koinexample.KoinSampleTests
koinexample.KoinSampleTests  Time elapsed: 0.009 sec  <<< ERROR!
java.lang.reflect.InvocationTargetException
        at koinexample.KoinSampleTests.getKoin(KoinSampleTests.kt:26)
        at koinexample.KoinSampleTests.<init>(KoinSampleTests.kt:61)

Я создал небольшой пример на GitHub, который воспроизводит эту ошибку: https://github.com/elifarley/kotlin-tests-with-koin-examples

Просто выполните эти команды, чтобы клонировать репо и запустить тесты:

git clone https://github.com/elifarley/kotlin-tests-with-koin-examples.git
cd kotlin-tests-with-koin-examples
mvn

Вот основной Kotlin файл:

package koinexample

import io.kotlintest.koin.KoinListener
import io.kotlintest.shouldBe
import io.kotlintest.specs.FreeSpec
import org.koin.core.inject
import org.koin.dsl.module
import org.koin.test.KoinTest

data class Stats(var ok: Long = 0, var error: Long = 0)

interface StatsServer {
    fun newError(): Long
}

class StatsServerSimple(private val stats: Stats) : StatsServer {
    override fun newError() = stats.error++
}

val appModule = module {
    single { Stats() }
    single { StatsServerSimple(get()) as StatsServer }
}

class KoinSampleTests : FreeSpec(), KoinTest {

    private val modules = listOf(
        appModule
    )

    override fun listeners() = listOf(KoinListener(modules))

    val statsServer: StatsServer by inject()

    init {

        "Happy path" {
            statsServer.newError() shouldBe 1
        }
    }
}

Ответы [ 2 ]

1 голос
/ 05 марта 2020

Ваша проблема заключается в простой путанице при импорте.

Обратите внимание, что вы используете import org.koin.core.inject, а именно эта функция:

inline fun <reified T> KoinComponent.inject(
        qualifier: Qualifier? = null,
        noinline parameters: ParametersDefinition? = null
): Lazy<T> =
        getKoin().inject(qualifier, parameters)

Для работы требуется getKoin и, следовательно, вы не можете инициализировать свой тест (тестовый класс инициализируется до того, как Коин сможет начать со слушателя).

Правильный импорт - import org.koin.test.inject, что означает:

inline fun <reified T> KoinTest.inject(
    qualifier: Qualifier? = null,
    noinline parameters: ParametersDefinition? = null
): Lazy<T> = lazy { get<T>(qualifier, parameters) }

Обратите внимание, что это действительно лениво, поэтому Kotest будет иметь возможность инициализировать Koin до начала ваших тестов.

Исправление этого импорта должно решить эту проблему

0 голосов
/ 03 марта 2020

Похоже, вы никогда не запускаете приложение Koin. Вам нужно иметь

startKoin {
            modules(appModule)
        }

в вашем методе тестирования или в beforeSpec / beforeTest вызове функции spe c.

Или использовать что-то вроде здесь:

    override fun listeners() = listOf(KoinListener(appModule))

, который описан в документации для kotlintest / kotest: https://github.com/Kotest/Kotest/blob/master/doc/extensions.md#koin

...