InsertKoinIO / koin

Koin - a pragmatic lightweight dependency injection framework for Kotlin & Kotlin Multiplatform
https://insert-koin.io
Apache License 2.0
9.12k stars 721 forks source link

Trying to inject MongoClient does not pass verification #1888

Open jfontsaballs opened 6 months ago

jfontsaballs commented 6 months ago

Describe the bug This test throws:

import com.mongodb.kotlin.client.coroutine.MongoClient
import org.koin.core.annotation.KoinExperimentalAPI
import org.koin.dsl.module
import org.koin.test.verify.verify
import kotlin.test.Test

class DependencyInjectionTest {
    @OptIn(KoinExperimentalAPI::class)
    @Test
    fun verifyDependencyInjectionMongo() {
        module {
            single { MongoClient.create("") }
        }.verify()
    }
}
Verifying module 'org.koin.core.module.Module@3efa40e5' ...

|-> definition [Singleton:'com.mongodb.kotlin.client.coroutine.MongoClient']
| bind types: [class com.mongodb.kotlin.client.coroutine.MongoClient]
| 1 dependencies to check
* ----- > Missing definition type 'com.mongodb.reactivestreams.client.MongoClient' in definition '[Singleton:'com.mongodb.kotlin.client.coroutine.MongoClient']'
Fix your Koin configuration or add extraTypes parameter to whitelist the type: verify(extraTypes = listOf(com.mongodb.reactivestreams.client.MongoClient::class))

Missing definition type 'com.mongodb.reactivestreams.client.MongoClient' in definition '[Singleton:'com.mongodb.kotlin.client.coroutine.MongoClient']'
org.koin.test.verify.MissingKoinDefinitionException: Missing definition type 'com.mongodb.reactivestreams.client.MongoClient' in definition '[Singleton:'com.mongodb.kotlin.client.coroutine.MongoClient']'
    at org.koin.test.verify.Verification.verifyConstructor(Verification.kt:85)
    at org.koin.test.verify.Verification.verifyFactory(Verification.kt:49)
    at org.koin.test.verify.Verification.verify(Verification.kt:26)
    at org.koin.test.verify.Verify.verify(VerifyModule.kt:71)
    at org.koin.test.verify.VerifyModuleKt.verify(VerifyModule.kt:17)
    at org.koin.test.verify.VerifyModuleKt.verify$default(VerifyModule.kt:17)

To Reproduce Run the test.

Expected behavior Verification passes as there is only a singleton configured with no dependencies.

Koin module and version:

[versions]
koin = "3.5.6"
mongodbDriverKotlinCoroutine = "5.1.0"

[libraries]
koin-core = { module = "io.insert-koin:koin-core", version.ref = "koin" }
koin-ktor = { module = "io.insert-koin:koin-ktor", version.ref = "koin" }
koin-logger-slf4j = { module = "io.insert-koin:koin-logger-slf4j", version.ref = "koin" }
koin-test = { module = "io.insert-koin:koin-test", version.ref = "koin" }
mongodb-driver-kotlin-coroutine = { module = "org.mongodb:mongodb-driver-kotlin-coroutine", version.ref = "mongodbDriverKotlinCoroutine" }

Snippet or Sample project to help reproduce See test above.

jfontsaballs commented 6 months ago

After some more testing, it seems the problem is that verify uses the constructor parameter list even if, in the module, the instance is constructed inside a lambda which does not use that constructor or that manually passes constructor parameters or uses default values.

Here is a small snippet that I think shows the problem:

class MyClass(val myDependency: okhttp3.HttpUrl = "https://google.com".toHttpUrl())

module {
    single { MyClass() } //This works perfectly at runtime but will throw during verification
}
arnaudgiuliani commented 4 months ago

Yeah, you are declaring a function definition here. Verify is not fully stable on that. You could better extract a function to be called in the definition. Give a try