BAEL-1462 Kotlin DI with Kodein (#3544)
* BAEL-1462 Kotlin DI with Kodein * BAEL-1462 Kotlin DI with Kodein * applied editor's suggestions * removed unnecessary curly braces * Moved kodein files into core-kotlin as per editor's review * Using assertj instead of junit assertions as per editor's instruction
This commit is contained in:
parent
30285c1c18
commit
ef1b033b78
|
@ -76,7 +76,18 @@
|
|||
<artifactId>mockito-kotlin</artifactId>
|
||||
<version>${mockito-kotlin.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.salomonbrys.kodein</groupId>
|
||||
<artifactId>kodein</artifactId>
|
||||
<version>${kodein.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<version>${assertj.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
@ -189,11 +200,13 @@
|
|||
<kotlin-reflect.version>1.1.2</kotlin-reflect.version>
|
||||
<kotlinx.version>0.15</kotlinx.version>
|
||||
<mockito-kotlin.version>1.5.0</mockito-kotlin.version>
|
||||
<kodein.version>4.1.0</kodein.version>
|
||||
|
||||
<junit.jupiter.version>5.0.0</junit.jupiter.version>
|
||||
<junit.platform.version>1.0.0</junit.platform.version>
|
||||
<junit.vintage.version>4.12.0</junit.vintage.version>
|
||||
<junit4.version>4.12</junit4.version>
|
||||
<assertj.version>3.9.1</assertj.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
package com.baeldung.kotlin.kodein
|
||||
|
||||
class Controller(private val service : Service)
|
|
@ -0,0 +1,3 @@
|
|||
package com.baeldung.kotlin.kodein
|
||||
|
||||
interface Dao
|
|
@ -0,0 +1,3 @@
|
|||
package com.baeldung.kotlin.kodein
|
||||
|
||||
class JdbcDao : Dao
|
|
@ -0,0 +1,3 @@
|
|||
package com.baeldung.kotlin.kodein
|
||||
|
||||
class MongoDao : Dao
|
|
@ -0,0 +1,3 @@
|
|||
package com.baeldung.kotlin.kodein
|
||||
|
||||
class Service(private val dao: Dao, private val tag: String)
|
|
@ -0,0 +1,191 @@
|
|||
package com.baeldung.kotlin.kodein
|
||||
|
||||
import com.github.salomonbrys.kodein.*
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Test
|
||||
|
||||
class KodeinUnitTest {
|
||||
|
||||
class InMemoryDao : Dao
|
||||
|
||||
@Test
|
||||
fun whenSingletonBinding_thenSingleInstanceIsCreated() {
|
||||
var created = false
|
||||
val kodein = Kodein {
|
||||
bind<Dao>() with singleton {
|
||||
created = true
|
||||
MongoDao()
|
||||
}
|
||||
}
|
||||
|
||||
assertThat(created).isFalse()
|
||||
|
||||
val dao1: Dao = kodein.instance()
|
||||
|
||||
assertThat(created).isTrue()
|
||||
|
||||
val dao2: Dao = kodein.instance()
|
||||
|
||||
assertThat(dao1).isSameAs(dao2)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenFactoryBinding_thenNewInstanceIsCreated() {
|
||||
val kodein = Kodein {
|
||||
bind<Dao>() with singleton { MongoDao() }
|
||||
bind<Service>() with factory { tag: String -> Service(instance(), tag) }
|
||||
}
|
||||
val service1: Service = kodein.with("myTag").instance()
|
||||
val service2: Service = kodein.with("myTag").instance()
|
||||
|
||||
assertThat(service1).isNotSameAs(service2)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenProviderBinding_thenNewInstanceIsCreated() {
|
||||
val kodein = Kodein {
|
||||
bind<Dao>() with provider { MongoDao() }
|
||||
}
|
||||
val dao1: Dao = kodein.instance()
|
||||
val dao2: Dao = kodein.instance()
|
||||
|
||||
assertThat(dao1).isNotSameAs(dao2)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenTaggedBinding_thenMultipleInstancesOfSameTypeCanBeRegistered() {
|
||||
val kodein = Kodein {
|
||||
bind<Dao>("dao1") with singleton { MongoDao() }
|
||||
bind<Dao>("dao2") with singleton { MongoDao() }
|
||||
}
|
||||
val dao1: Dao = kodein.instance("dao1")
|
||||
val dao2: Dao = kodein.instance("dao2")
|
||||
|
||||
assertThat(dao1).isNotSameAs(dao2)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenEagerSingletonBinding_thenCreationIsEager() {
|
||||
var created = false
|
||||
val kodein = Kodein {
|
||||
bind<Dao>() with eagerSingleton {
|
||||
created = true
|
||||
MongoDao()
|
||||
}
|
||||
}
|
||||
|
||||
assertThat(created).isTrue()
|
||||
val dao1: Dao = kodein.instance()
|
||||
val dao2: Dao = kodein.instance()
|
||||
|
||||
assertThat(dao1).isSameAs(dao2)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenMultitonBinding_thenInstancesAreReused() {
|
||||
val kodein = Kodein {
|
||||
bind<Dao>() with singleton { MongoDao() }
|
||||
bind<Service>() with multiton { tag: String -> Service(instance(), tag) }
|
||||
}
|
||||
val service1: Service = kodein.with("myTag").instance()
|
||||
val service2: Service = kodein.with("myTag").instance()
|
||||
|
||||
assertThat(service1).isSameAs(service2)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenInstanceBinding_thenItIsReused() {
|
||||
val dao = MongoDao()
|
||||
val kodein = Kodein {
|
||||
bind<Dao>() with instance(dao)
|
||||
}
|
||||
val fromContainer: Dao = kodein.instance()
|
||||
|
||||
assertThat(dao).isSameAs(fromContainer)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenConstantBinding_thenItIsAvailable() {
|
||||
val kodein = Kodein {
|
||||
constant("magic") with 42
|
||||
}
|
||||
val fromContainer: Int = kodein.instance("magic")
|
||||
|
||||
assertThat(fromContainer).isEqualTo(42)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenUsingModules_thenTransitiveDependenciesAreSuccessfullyResolved() {
|
||||
val jdbcModule = Kodein.Module {
|
||||
bind<Dao>() with singleton { JdbcDao() }
|
||||
}
|
||||
val kodein = Kodein {
|
||||
import(jdbcModule)
|
||||
bind<Controller>() with singleton { Controller(instance()) }
|
||||
bind<Service>() with singleton { Service(instance(), "myService") }
|
||||
}
|
||||
|
||||
val dao: Dao = kodein.instance()
|
||||
assertThat(dao).isInstanceOf(JdbcDao::class.java)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenComposition_thenBeansAreReUsed() {
|
||||
val persistenceContainer = Kodein {
|
||||
bind<Dao>() with singleton { MongoDao() }
|
||||
}
|
||||
val serviceContainer = Kodein {
|
||||
extend(persistenceContainer)
|
||||
bind<Service>() with singleton { Service(instance(), "myService") }
|
||||
}
|
||||
val fromPersistence: Dao = persistenceContainer.instance()
|
||||
val fromService: Dao = serviceContainer.instance()
|
||||
|
||||
assertThat(fromPersistence).isSameAs(fromService)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenOverriding_thenRightBeanIsUsed() {
|
||||
val commonModule = Kodein.Module {
|
||||
bind<Dao>() with singleton { MongoDao() }
|
||||
bind<Service>() with singleton { Service(instance(), "myService") }
|
||||
}
|
||||
val testContainer = Kodein {
|
||||
import(commonModule)
|
||||
bind<Dao>(overrides = true) with singleton { InMemoryDao() }
|
||||
}
|
||||
val dao: Dao = testContainer.instance()
|
||||
|
||||
assertThat(dao).isInstanceOf(InMemoryDao::class.java)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenMultiBinding_thenWorks() {
|
||||
val kodein = Kodein {
|
||||
bind() from setBinding<Dao>()
|
||||
bind<Dao>().inSet() with singleton { MongoDao() }
|
||||
bind<Dao>().inSet() with singleton { JdbcDao() }
|
||||
}
|
||||
val daos: Set<Dao> = kodein.instance()
|
||||
|
||||
assertThat(daos.map { it.javaClass as Class<*> }).containsOnly(MongoDao::class.java, JdbcDao::class.java)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenInjector_thenWorks() {
|
||||
class Controller2 {
|
||||
private val injector = KodeinInjector()
|
||||
val service: Service by injector.instance()
|
||||
fun injectDependencies(kodein: Kodein) = injector.inject(kodein)
|
||||
}
|
||||
|
||||
val kodein = Kodein {
|
||||
bind<Dao>() with singleton { MongoDao() }
|
||||
bind<Service>() with singleton { Service(instance(), "myService") }
|
||||
}
|
||||
val controller = Controller2()
|
||||
controller.injectDependencies(kodein)
|
||||
|
||||
assertThat(controller.service).isNotNull
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue