Skip to content

Commit

Permalink
Merge pull request #747 from splendo/bugfix/732-koin-cleanup-improvem…
Browse files Browse the repository at this point in the history
…ents

Koin Cleanup improvements
  • Loading branch information
Daeda88 authored Nov 23, 2023
2 parents 62660d5 + f5185a8 commit 2e9fe31
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 11 deletions.
1 change: 1 addition & 0 deletions test-utils-base/api/androidLib/test-utils-base.api
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public class com/splendo/kaluga/test/base/BaseTest {
public abstract class com/splendo/kaluga/test/base/BaseUIThreadTest : com/splendo/kaluga/test/base/BaseTest {
public fun <init> ()V
public abstract fun getCreateTestContextWithConfiguration ()Lkotlin/jvm/functions/Function3;
public fun getOnFailedToCreateTestContextWithConfiguration ()Lkotlin/jvm/functions/Function1;
public final fun testOnUIThread (Ljava/lang/Object;ZLkotlin/jvm/functions/Function2;)V
public static synthetic fun testOnUIThread$default (Lcom/splendo/kaluga/test/base/BaseUIThreadTest;Ljava/lang/Object;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)V
}
Expand Down
1 change: 1 addition & 0 deletions test-utils-base/api/jvm/test-utils-base.api
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public class com/splendo/kaluga/test/base/BaseTest {
public abstract class com/splendo/kaluga/test/base/BaseUIThreadTest : com/splendo/kaluga/test/base/BaseTest {
public fun <init> ()V
public abstract fun getCreateTestContextWithConfiguration ()Lkotlin/jvm/functions/Function3;
public fun getOnFailedToCreateTestContextWithConfiguration ()Lkotlin/jvm/functions/Function1;
public final fun testOnUIThread (Ljava/lang/Object;ZLkotlin/jvm/functions/Function2;)V
public static synthetic fun testOnUIThread$default (Lcom/splendo/kaluga/test/base/BaseUIThreadTest;Ljava/lang/Object;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)V
}
Expand Down
9 changes: 8 additions & 1 deletion test-utils-base/src/commonMain/kotlin/ui_thread_testing.kt
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ abstract class BaseUIThreadTest<Configuration, Context : BaseUIThreadTest.TestCo
* Creates the TestContext based on Configuration and CoroutineScope
*/
abstract val createTestContextWithConfiguration: suspend (configuration: Configuration, scope: CoroutineScope) -> Context
open val onFailedToCreateTestContextWithConfiguration: (configuration: Configuration) -> Unit = {}

private companion object {
val cancellationException = CancellationException("Scope canceled by testOnUIThread because cancelScopeAfterTest was set to true.")
Expand All @@ -127,8 +128,14 @@ abstract class BaseUIThreadTest<Configuration, Context : BaseUIThreadTest.TestCo
fun testOnUIThread(configuration: Configuration, cancelScopeAfterTest: Boolean = false, block: suspend Context.() -> Unit) {
try {
val createTestContextWithConfiguration = createTestContextWithConfiguration
val onFailedToCreateTestContextWithConfiguration = onFailedToCreateTestContextWithConfiguration
val test: suspend (CoroutineScope) -> Unit = {
val testContext = createTestContextWithConfiguration(configuration, it)
val testContext = try {
createTestContextWithConfiguration(configuration, it)
} catch (e: Throwable) {
onFailedToCreateTestContextWithConfiguration(configuration)
throw e
}
yield()
try {
block(testContext)
Expand Down
1 change: 1 addition & 0 deletions test-utils-koin/api/androidLib/test-utils-koin.api
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ public abstract class com/splendo/kaluga/test/koin/BaseKoinFlowTest : com/splend

public abstract class com/splendo/kaluga/test/koin/BaseKoinUIThreadTest : com/splendo/kaluga/test/base/BaseUIThreadTest {
public fun <init> ()V
public fun getOnFailedToCreateTestContextWithConfiguration ()Lkotlin/jvm/functions/Function1;
}

public class com/splendo/kaluga/test/koin/BaseKoinUIThreadTest$KoinTestContext : com/splendo/kaluga/test/base/BaseUIThreadTest$TestContext, org/koin/core/component/KoinComponent {
Expand Down
1 change: 1 addition & 0 deletions test-utils-koin/api/jvm/test-utils-koin.api
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ public abstract class com/splendo/kaluga/test/koin/BaseKoinFlowTest : com/splend

public abstract class com/splendo/kaluga/test/koin/BaseKoinUIThreadTest : com/splendo/kaluga/test/base/BaseUIThreadTest {
public fun <init> ()V
public fun getOnFailedToCreateTestContextWithConfiguration ()Lkotlin/jvm/functions/Function1;
}

public class com/splendo/kaluga/test/koin/BaseKoinUIThreadTest$KoinTestContext : com/splendo/kaluga/test/base/BaseUIThreadTest$TestContext, org/koin/core/component/KoinComponent {
Expand Down
16 changes: 12 additions & 4 deletions test-utils-koin/src/commonMain/kotlin/KoinUIThreadTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,23 @@ abstract class BaseKoinUIThreadTest<C, TC : BaseKoinUIThreadTest.KoinTestContext
)

init {
startKoin {
appDeclaration?.invoke(this)
modules(koinModules)
stopKoin()
try {
startKoin {
appDeclaration?.invoke(this)
modules(koinModules)
}
loadKoinModules(koinModules.toList())
} catch (error: Throwable) {
stopKoin()
throw error
}
loadKoinModules(koinModules.toList())
}

override fun dispose() {
stopKoin()
}
}

override val onFailedToCreateTestContextWithConfiguration: (configuration: C) -> Unit = { stopKoin() }
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ package com.splendo.kaluga.test.koin
import com.splendo.kaluga.architecture.viewmodel.LifecycleViewModel
import com.splendo.kaluga.test.architecture.BaseUIThreadViewModelTest
import com.splendo.kaluga.test.architecture.UIThreadViewModelTest
import com.splendo.kaluga.test.architecture.viewmodel.cleanUp
import org.koin.core.context.stopKoin
import org.koin.core.module.Module
import org.koin.dsl.KoinAppDeclaration

Expand All @@ -40,8 +38,8 @@ abstract class KoinUIThreadViewModelTest<Context : KoinUIThreadViewModelTest.Koi
)

override fun dispose() {
viewModel.cleanUp()
stopKoin()
super<UIThreadViewModelTest.ViewModelTestContext>.dispose()
super<KoinTestContext>.dispose()
}
}
}
Expand All @@ -60,8 +58,8 @@ abstract class BaseKoinUIThreadViewModelTest<Configuration, Context : BaseKoinUI
koinModules.toList(),
)
override fun dispose() {
viewModel.cleanUp()
stopKoin()
super<BaseUIThreadViewModelTest.ViewModelTestContext>.dispose()
super<KoinTestContext>.dispose()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
Copyright 2023 Splendo Consulting B.V. The Netherlands
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package com.splendo.kaluga.test.koin

import kotlinx.coroutines.CoroutineScope
import org.koin.core.component.inject
import org.koin.core.context.startKoin
import org.koin.core.error.InstanceCreationException
import org.koin.dsl.module
import org.koin.mp.KoinPlatformTools
import kotlin.test.AfterTest
import kotlin.test.Test
import kotlin.test.assertFails
import kotlin.test.assertFailsWith
import kotlin.test.assertNull

class KoinTestContextFailureTest {

class MockClass

interface MockKoinComponent {
val mockClass: MockClass
}

class MockKoinComponentImpl(override val mockClass: MockClass) : MockKoinComponent

class MockKoinUIThreadTest : KoinUIThreadTest<MockKoinUIThreadTest.Context>() {
object Context : KoinUIThreadTest.KoinTestContext(
koinModules = listOf(
module {
single<MockKoinComponent> { MockKoinComponentImpl(get()) }
},
),
) {
val component: MockKoinComponent by inject()
val mockClass = component.mockClass
}

override val createTestContext: suspend (scope: CoroutineScope) -> Context = { Context }
}

@AfterTest
fun validateKoinCleaned() {
assertNull(KoinPlatformTools.defaultContext().getOrNull())
}

@Test
fun testKoinAlreadyStarted() {
startKoin {}
val context = BaseKoinUIThreadTest.KoinTestContext()
context.dispose()
}

@Test
fun testModuleContainsMissingDefinitions() {
assertFailsWith<InstanceCreationException> {
BaseKoinUIThreadTest.KoinTestContext(
koinModules = listOf(
module {
single<MockKoinComponent>(createdAtStart = true) { MockKoinComponentImpl(get()) }
},
),
)
}
}

@Test
fun testKoinUIThreadTestContextContainsMissingDefinitions() {
val testClass = MockKoinUIThreadTest()
assertFails { testClass.testOnUIThread { } }
}
}

0 comments on commit 2e9fe31

Please sign in to comment.