koin icon indicating copy to clipboard operation
koin copied to clipboard

Koin module verification fails

Open MolchanovDmitry opened this issue 1 year ago • 1 comments

Describe the bug

  1. Koin module verification fails when initialize class in definition block.
  2. For CompositeDisposable dependency should add following extra types:
listOf(
    Iterable::class,
    Array<Disposable>::class,
)

To Reproduce Steps to reproduce the behavior:

  1. Create android project
  2. Add rxJava2 dep io.reactivex.rxjava2:rxjava:2.2.8
  3. Create koin module with CompositeDisposable dependency
  4. Initialize some class in definition block.

Expected behavior Test passes without adding additional extra types

Koin module and version: koin-android:3.5.6 koin-test:3.5.6

Snippet or Sample project to help reproduce

AppModule.kt

import io.reactivex.disposables.CompositeDisposable
import org.koin.dsl.module

class A
class B(val compositeDisposable: CompositeDisposable, val a: A)

val appModule = module {

    single { CompositeDisposable() }

    single { B(get(), A()) }
}

KoinVerificationTest.kt

class KoinVerificationTest {

    /** uncomment extra types for test pass */
    @Test
    fun `koin verification test`(){
        appModule.verify(extraTypes = listOf(
            //A::class,
            //Iterable::class,
            //Array<Disposable>::class,
        ))
    }
}

MolchanovDmitry avatar Jun 25 '24 12:06 MolchanovDmitry

in your case, class A is missing?

arnaudgiuliani avatar Jul 25 '24 15:07 arnaudgiuliani

Hi team 👋 Any updates on this?

We can reproduce this issue by simply put this.

data class A(val b: B)
data class B(val value: Int)

module {
  single { A(B(1)) }
}.verify() // this would fail because it tries to look up B instance based on A's constructor.

I think the problem here is it looks up the dependency from A's constructor even though A's factory is explicitly given - which doesn't make sense.

checkModule was covering this case, but now it's deprecated.

jun-tomioka avatar Dec 05 '24 03:12 jun-tomioka

I seem to have this or similar problem as well. In my case, I have multi module (Kotlin MP) project where one module has ClassA defined as singleton. Calling verifyAll() or verify() fails with message that ClassA is missing while checkModules works fine. Obviously running the project works as well, the modules are correct. Not sure how is verify different from checkModules but it seems to me that checkModules was deprecated too early.

lsrom avatar Dec 23 '24 18:12 lsrom

Yeah, Verify works on static type. It won't see easily things behind a lambda. CheckModules was interesting but hard to maintain on the long :/

This point here is about default value. This could be a point 🤔

arnaudgiuliani avatar Jan 16 '25 16:01 arnaudgiuliani

@arnaudgiuliani Hi. I'm not sure if my issue related to this but it seems very similar.

I have this definition in android module:

single<AccountManager> { AccountManager.get(androidContext()) }

and verification fails:

* ----- > Missing definition for '[field:'arg1' - type:'android.accounts.IAccountManager']' in definition '[Singleton: 'android.accounts.AccountManager',binds:android.accounts.AccountManager]'.
- Fix your Koin configuration -
1- add missing definition for type 'android.accounts.IAccountManager'. like: singleOf(::android.accounts.IAccountManager)
or
2- else define injection for 'android.accounts.AccountManager' with:
module.verify(
    injections = injectedParameters(
        definition<android.accounts.AccountManager>(android.accounts.IAccountManager::class)
    )
)

But I can't add android.accounts.IAccountManager::class because it is internal in android

How can I bypass this error?

MAX-POLKOVNIK avatar Jan 24 '25 05:01 MAX-POLKOVNIK

You can work by whitelisting the needed type: verify(extraTypes: List<KClass<*>> = emptyList(), injections: List<ParameterTypeInjection>? = emptyList())

You can declare it as extraTypes

arnaudgiuliani avatar Jan 28 '25 15:01 arnaudgiuliani

You can work by whitelisting the needed type: verify(extraTypes: List<KClass<*>> = emptyList(), injections: List<ParameterTypeInjection>? = emptyList())

You can declare it as extraTypes

Thanks! I have to retrieve KClass via reflection like this: Class.forName("android.accounts.IAccountManager").kotlin Luckily I do not have same situation with internals on iOS 'cause we do not have same ability in Kotlin/Native

MAX-POLKOVNIK avatar Feb 04 '25 07:02 MAX-POLKOVNIK

I fix it by:

definition<CompositeDisposable>(Array<Disposable>::class, Iterable::class)

TingGu-Tyro avatar Apr 25 '25 05:04 TingGu-Tyro

👍

arnaudgiuliani avatar Apr 30 '25 17:04 arnaudgiuliani