test case isolation #1411
-
I need to inject different instances of classes in my various JUnit tests that use Koin. When run one at a time, the tests pass, but when run all together, they fail. Test foo is producing values that could only come from the objected injected in test bar, so I must not be properly isolating Koin. The actual tests are more complicated integration tests, and the sample below was my attempt to make something self-contained that reproduces the issue, but unfortunately these tests pass when run together. The structure is the same, though. import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
import org.koin.core.context.GlobalContext.startKoin
import org.koin.core.context.GlobalContext.stopKoin
import org.koin.test.KoinTest
import org.koin.test.mock.declare
import kotlin.time.Duration.Companion.seconds
class KoinSampleTest : KoinTest {
@Before
fun setup() {
startKoin { }
}
@After
fun teardown() = stopKoin()
@Test
fun foo() = runBlocking<Unit> {
val namedUser = Foo()
declare<Named> { namedUser }
val user = NamedUser()
assertThat(user.sayName()).isEqualTo("foo")
}
@Test
fun bar() = runBlocking<Unit> {
val namedUser = Bar()
declare<Named> { namedUser }
val user = NamedUser()
assertThat(user.sayName()).isEqualTo("bar")
}
}
interface Named {
val name: String
}
class Foo(override val name: String = "foo") : Named
class Bar(override val name: String = "bar") : Named
class NamedUser : KoinComponent {
val nameContainer by inject<Named>()
suspend fun sayName(): String {
delay(2.seconds) // simulate some latency of in-process RPC
return nameContainer.name
}
} Are there some best practices for KoinTest that I'm missing here? |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
I was injecting a field into an |
Beta Was this translation helpful? Give feedback.
I was injecting a field into an
object
, not aclass
, so Kotlin was doing what I asked and only ever instantiating the injected field once. A language-level singleton has has a larger scope than a Koin singleton. See my example test at https://stackoverflow.com/a/73422425/821287