Skip to content

Commit

Permalink
Add support for Lazy
Browse files Browse the repository at this point in the history
  • Loading branch information
ILIYANGERMANOV committed Aug 25, 2024
1 parent ac083aa commit e928184
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 2 deletions.
9 changes: 7 additions & 2 deletions di/src/commonMain/kotlin/ivy/di/DiContainer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,14 @@ object Di {
register<Base> { get<Impl>(named = named) }
}

inline fun <reified T : Any> getLazy(named: Any? = null): Lazy<T> {
factoryOrThrow(T::class, named) // ensure that factory exists
return lazy { get<T>(named) }
}

inline fun <reified T : Any> get(named: Any? = null): T {
val classKey = T::class
val (scope, factory) = factory(classKey, named)
val (scope, factory) = factoryOrThrow(classKey, named)
val depKey = DependencyKey(scope, classKey, named)
return if (classKey in singletons) {
if (depKey in singletonInstances) {
Expand All @@ -69,7 +74,7 @@ object Di {
}
}

fun factory(
fun factoryOrThrow(
classKey: KClass<*>,
named: Any?,
): Pair<Scope, Factory> = scopes
Expand Down
102 changes: 102 additions & 0 deletions di/src/commonTest/kotlin/ivy/di/LazyTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package ivy.di

import io.kotest.assertions.throwables.shouldThrow
import io.kotest.matchers.shouldBe
import ivy.di.Di.register
import ivy.di.Di.singleton
import kotlin.test.BeforeTest
import kotlin.test.Test

private var initialized = false

class Counter(var x: Int) {
init {
initialized = true
}
}

class CountManager(private val counter: Lazy<Counter>) {
fun increment() {
counter.value.x++
}
}

class LazyTest {

@BeforeTest
fun setup() {
Di.reset()
initialized = false
}

@Test
fun lazyInitialization() {
// Given
Di.appScope {
register { Counter(x = 42) }
}

// When
val lazyCounter = Di.getLazy<Counter>()

// Initially the lazy counter isn't initialized
initialized shouldBe false

// When the lazy value is accessed
val counter = lazyCounter.value

// Then
initialized shouldBe true
counter.x shouldBe 42
}

@Test
fun lazySingletonInitialization() {
// Given
Di.appScope {
singleton { Counter(x = 0) }
}

// When
val lazyCounter = Di.getLazy<Counter>()

// Initially the lazy counter isn't initialized
initialized shouldBe false

// When the lazy value is accessed and modified
lazyCounter.value.x shouldBe 0
lazyCounter.value.x = 42

// Then
initialized shouldBe true
Di.getLazy<Counter>().value.x shouldBe 42
}

@Test
fun missingFactory() {
// When-Then
shouldThrow<DependencyInjectionError> {
Di.getLazy<Counter>()
}
}

@Test
fun realWorldScenario() {
// Given
Di.appScope {
singleton { Counter(x = 0) }
register { CountManager(Di.getLazy()) }
}
val manager = Di.get<CountManager>()

// Initially the lazy counter isn't initialized
initialized shouldBe false

// When
manager.increment()

// Then
initialized shouldBe true
Di.get<Counter>().x shouldBe 1
}
}

0 comments on commit e928184

Please sign in to comment.