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

Possible issue with checkModules{} when passing parameters from one dependency to another #806

Closed iliaskomp closed 4 years ago

iliaskomp commented 4 years ago

Koin project used and used version: Android project org.koin:koin-android:2.1.5

Describe the bug Below I have a factory of Completable which needs a string parameter. The TestClass dependency has a dependency on Completable and passes a "default" string.

    factory<Completable>(named(TEST)) { (string: String?) ->
        var completable = Completable.complete()
        completable = completable.andThen(doMethod(string ?: "default"))
        completable
    }

    single<TestClass> {
        TestClassImpl(get(), get<Completable>(named(TEST)) { parametersOf("default") })
    }

While it seems on runtime to work correctly (no crashes), when I run the checkModules {} function there is an error.

checkModules {} test

class KoinTest {

    @Test
    fun `test koin definition tree`() {
        checkModules {
            androidContext(ApplicationProvider.getApplicationContext())
            modules(module1)
            modules(module2)
            modules(module3)
        }
    }
}

Error

[ERROR] [Koin] Instance creation error : could not create instance for [Factory:'io.reactivex.Completable',qualifier:TEST]: org.koin.core.error.NoParameterFoundException: Can't get parameter value #0 from org.koin.core.parameter.DefinitionParameters@12b27d15
    org.koin.core.parameter.DefinitionParameters.elementAt(DefinitionParameters.kt:32)
    org.koin.core.parameter.DefinitionParameters.component1(DefinitionParameters.kt:34)
    at.xxx.dependency.koin.Module1Kt$module1$1$5.invoke(Module1.kt)
    at.xxx.dependency.koin.Module1Kt$module1$1$5.invoke(Module1.kt)
    org.koin.core.instance.InstanceFactory.create(InstanceFactory.kt:50)
    org.koin.core.instance.FactoryInstanceFactory.get(FactoryInstanceFactory.kt:36)
    org.koin.core.registry.InstanceRegistry.resolveInstance$koin_core(InstanceRegistry.kt:87)
    org.koin.core.scope.Scope.resolveInstance(Scope.kt:214)
    org.koin.core.scope.Scope.get(Scope.kt:181)
    org.koin.test.check.CheckModulesKt.runDefinition(CheckModules.kt:86)
    org.koin.test.check.CheckModulesKt.runScope(CheckModules.kt:78)
    org.koin.test.check.CheckModulesKt.checkScopedDefinitions(CheckModules.kt:70)
    org.koin.test.check.CheckModulesKt.checkModules(CheckModules.kt:50)
    org.koin.test.check.CheckModulesKt.checkModules(CheckModules.kt:32)
    org.koin.test.check.CheckModulesKt.checkModules(CheckModules.kt:40)
    org.koin.test.check.CheckModulesKt.checkModules$default(CheckModules.kt:37)
    at.xxx.dependency.koin.KoinTest.test koin definition tree(KoinTest.kt:17)

org.koin.core.error.InstanceCreationException: Could not create instance for [Factory:'io.reactivex.Completable',qualifier:TEST]

    at org.koin.core.instance.InstanceFactory.create(InstanceFactory.kt:59)
    at org.koin.core.instance.FactoryInstanceFactory.get(FactoryInstanceFactory.kt:36)
    at org.koin.core.registry.InstanceRegistry.resolveInstance$koin_core(InstanceRegistry.kt:87)
    at org.koin.core.scope.Scope.resolveInstance(Scope.kt:214)
    at org.koin.core.scope.Scope.get(Scope.kt:181)
    at org.koin.test.check.CheckModulesKt.runDefinition(CheckModules.kt:86)
    at org.koin.test.check.CheckModulesKt.runScope(CheckModules.kt:78)
    at org.koin.test.check.CheckModulesKt.checkScopedDefinitions(CheckModules.kt:70)
    at org.koin.test.check.CheckModulesKt.checkModules(CheckModules.kt:50)
    at org.koin.test.check.CheckModulesKt.checkModules(CheckModules.kt:32)
    at org.koin.test.check.CheckModulesKt.checkModules(CheckModules.kt:40)
    at org.koin.test.check.CheckModulesKt.checkModules$default(CheckModules.kt:37)
    at xxx.dependency.koin.KoinTest.test koin definition tree(KoinTest.kt:17)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.robolectric.RobolectricTestRunner$HelperTestRunner$1.evaluate(RobolectricTestRunner.java:546)
    at org.robolectric.internal.SandboxTestRunner$2.lambda$evaluate$0(SandboxTestRunner.java:252)
    at org.robolectric.internal.bytecode.Sandbox.lambda$runOnMainThread$0(Sandbox.java:89)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
Caused by: org.koin.core.error.NoParameterFoundException: Can't get parameter value #0 from org.koin.core.parameter.DefinitionParameters@12b27d15
    at org.koin.core.parameter.DefinitionParameters.elementAt(DefinitionParameters.kt:32)
    at org.koin.core.parameter.DefinitionParameters.component1(DefinitionParameters.kt:34)
    at xxx.dependency.koin.Module1Kt$module1$1$5.invoke(Module1.kt)
    at xxx.dependency.koin.Module1Kt$module1$1$5.invoke(Module1.kt)
    at org.koin.core.instance.InstanceFactory.create(InstanceFactory.kt:50)
    ... 27 more

If I remove the string parameter, the test passes successfully.

I don't see any issue with the usage of the parameters or checkModules { } functionality. Could there be an issue with checkModules {}. Is there some solution in order to make the test pass?

erickok commented 4 years ago

You are not quite using the checkModules function correctly. A full example with parameter-dependent dependencies can be seen in the Koin tests: https://github.com/InsertKoinIO/koin/blob/master/koin-projects/koin-test/src/test/kotlin/org/koin/test/CheckModulesTest.kt#L156

iliaskomp commented 4 years ago

Thank you, that works! I am closing the issue.