koin icon indicating copy to clipboard operation
koin copied to clipboard

Constructor DSL definition with qualifier overrides default definition

Open jns-codeworks opened this issue 8 months ago • 0 comments

When there are multiple definitions for the same type, one of which has a named qualifier applied, the named definition overrides the non named (default) definition:

class KoinInjectionTest : KoinTest {
    val myServiceA = MyService("a")
    val myServiceB = MyService("b")

    @Test
    @Throws(Exception::class)
    fun `should inject types`() {
        startKoin {
            modules(
                module {
                    singleOf<MyService>(::myServiceA)
                    singleOf<MyService>(::myServiceB) { named(myServiceB.id) }
                }
            )
        }

        val injectedServiceA = get<MyService>()
        val injectedServiceB = get<MyService>(named(myServiceB.id))

        assertEquals(myServiceA, injectedServiceA)  // error: injectedService == injectedServiceB 
        assertEquals(myServiceB, injectedServiceB)
    }

   data class MyService(val id: String)
}

According to the documentation I would expect to have both definitions available, so that get<MyService>() triggers the myServiceA definition.

By default, Koin will bind a definition by its type or by its name, if the type is already bound to a definition.

val myModule = module { single<Service> { ServiceImpl1() } single<Service>(named("test")) { ServiceImpl2() } }

Then: val service : Service by inject() will trigger the ServiceImpl1 definition val service : Service by inject(named("test")) will trigger the ServiceImpl2 definition

When I replace

singleOf(::myServiceB) { named(myServiceB.id) }

with

single(named(myServiceB.id)) { myServiceB }

everything works as expected

Koin module and version: 4.1.0 koin android koin compose koin core

jns-codeworks avatar Aug 02 '25 23:08 jns-codeworks