-
-
Notifications
You must be signed in to change notification settings - Fork 719
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1939 from pedrofsn/breaking_changes-issue_1938
Restoring CheckModules as deprecated code
- Loading branch information
Showing
4 changed files
with
297 additions
and
6 deletions.
There are no files selected for viewing
183 changes: 183 additions & 0 deletions
183
projects/core/koin-test/src/commonMain/kotlin/org/koin/test/check/CheckModules.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
/* | ||
* Copyright 2017-Present the original author or authors. | ||
* | ||
* 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. | ||
*/ | ||
@file:Suppress("UNUSED_PARAMETER") | ||
@file:OptIn(KoinInternalApi::class) | ||
|
||
package org.koin.test.check | ||
|
||
import org.koin.core.Koin | ||
import org.koin.core.KoinApplication | ||
import org.koin.core.annotation.KoinInternalApi | ||
import org.koin.core.context.startKoin | ||
import org.koin.core.context.stopKoin | ||
import org.koin.core.definition.BeanDefinition | ||
import org.koin.core.logger.Level | ||
import org.koin.core.module.Module | ||
import org.koin.core.parameter.ParametersHolder | ||
import org.koin.core.qualifier.Qualifier | ||
import org.koin.core.qualifier.TypeQualifier | ||
import org.koin.core.scope.Scope | ||
import org.koin.dsl.KoinAppDeclaration | ||
import org.koin.mp.KoinPlatformTools | ||
import org.koin.test.mock.MockProvider | ||
import org.koin.test.parameter.MockParameter | ||
|
||
//TODO TO BE DEPRECATED in 3.6 | ||
|
||
/** | ||
* Check all definition's dependencies - start all modules and check if definitions can run | ||
*/ | ||
@Deprecated( | ||
message = "Migrate to verify() API", | ||
replaceWith = ReplaceWith("org.koin.test.verify.Verify") | ||
) | ||
fun KoinApplication.checkModules(parameters: CheckParameters? = null) = koin.checkModules(parameters) | ||
|
||
/** | ||
* Verify Modules by running each definition | ||
* | ||
* @param level - Log level | ||
* @param parameters - parameter setup | ||
* @param appDeclaration - koin Application | ||
*/ | ||
@Deprecated( | ||
message = "Migrate to verify() API", | ||
replaceWith = ReplaceWith("org.koin.test.verify.Verify") | ||
) | ||
fun checkModules(level: Level = Level.INFO, parameters: CheckParameters? = null, appDeclaration: KoinAppDeclaration) { | ||
startKoin(appDeclaration) | ||
.logger(KoinPlatformTools.defaultLogger(level)) | ||
.checkModules(parameters) | ||
} | ||
|
||
/** | ||
* Check given modules directly | ||
* | ||
* @param modules - list of modules | ||
* @param appDeclaration - Koin app config if needed | ||
* @param parameters - Check parameters DSL | ||
*/ | ||
@Deprecated( | ||
message = "Migrate to verify() API", | ||
replaceWith = ReplaceWith("modules.verifyAll()", "org.koin.test.verify.verifyAll") | ||
) | ||
fun checkKoinModules(modules: List<Module>, appDeclaration: KoinAppDeclaration = {}, parameters: CheckParameters? = null) { | ||
startKoin(appDeclaration) | ||
.modules(modules) | ||
.checkModules(parameters) | ||
stopKoin() | ||
} | ||
|
||
/** | ||
* @see checkModules | ||
* | ||
* Deprecated | ||
*/ | ||
@Deprecated("use instead checkKoinModules(modules : List<Module>, appDeclaration: KoinAppDeclaration = {}, parameters: CheckParameters? = null)") | ||
fun checkKoinModules(level: Level = Level.INFO, parameters: CheckParameters? = null, appDeclaration: KoinAppDeclaration) { | ||
startKoin(appDeclaration) | ||
.logger(KoinPlatformTools.defaultLogger(level)) | ||
.checkModules(parameters) | ||
stopKoin() | ||
} | ||
|
||
/** | ||
* @see checkKoinModules | ||
* | ||
* Deprecated | ||
*/ | ||
@Deprecated("use instead checkKoinModules(modules : List<Module>, appDeclaration: KoinAppDeclaration = {}, parameters: CheckParameters? = null)") | ||
fun checkKoinModules(vararg modules: Module, level: Level = Level.INFO, parameters: CheckParameters? = null) { | ||
startKoin({}) | ||
.logger(KoinPlatformTools.defaultLogger(level)) | ||
.checkModules(parameters) | ||
stopKoin() | ||
} | ||
|
||
/** | ||
* Check all definition's dependencies - start all modules and check if definitions can run | ||
*/ | ||
@Deprecated( | ||
message = "Migrate to verify() API", | ||
replaceWith = ReplaceWith("org.koin.test.verify.Verify") | ||
) | ||
fun Koin.checkModules(parametersDefinition: CheckParameters? = null) { | ||
logger.info("[Check] checking modules ...") | ||
|
||
checkAllDefinitions( | ||
declareParameterCreators(parametersDefinition), | ||
) | ||
|
||
logger.info("[Check] All checked") | ||
close() | ||
} | ||
|
||
private fun Koin.declareParameterCreators(parametersDefinition: CheckParameters?) = | ||
ParametersBinding(this).also { binding -> parametersDefinition?.invoke(binding) } | ||
|
||
@OptIn(KoinInternalApi::class) | ||
private fun Koin.checkAllDefinitions(allParameters: ParametersBinding) { | ||
val scopes: List<Scope> = instantiateAllScopes(allParameters) | ||
allParameters.scopeLinks.forEach { scopeLink -> | ||
val linkTargets = scopes.filter { it.scopeQualifier == scopeLink.value } | ||
scopes.filter { it.scopeQualifier == scopeLink.key } | ||
.forEach { scope -> linkTargets.forEach { linkTarget -> scope.linkTo(linkTarget) } } | ||
} | ||
instanceRegistry.instances.values.toSet().forEach { factory -> | ||
checkDefinition(allParameters, factory.beanDefinition, scopes.first { it.scopeQualifier == factory.beanDefinition.scopeQualifier }) | ||
} | ||
} | ||
|
||
@OptIn(KoinInternalApi::class) | ||
private fun Koin.instantiateAllScopes(allParameters: ParametersBinding): List<Scope> { | ||
return scopeRegistry.scopeDefinitions.map { qualifier -> | ||
val sourceScopeValue = mockSourceValue(qualifier) | ||
getOrCreateScope(qualifier.value, qualifier, sourceScopeValue) | ||
} | ||
} | ||
|
||
private fun mockSourceValue(qualifier: Qualifier): Any? { | ||
return if (qualifier is TypeQualifier) { | ||
MockProvider.makeMock(qualifier.type) | ||
} else { | ||
null | ||
} | ||
} | ||
|
||
private fun Koin.checkDefinition( | ||
allParameters: ParametersBinding, | ||
definition: BeanDefinition<*>, | ||
scope: Scope, | ||
) { | ||
val parameters: ParametersHolder = allParameters.parametersCreators[ | ||
CheckedComponent( | ||
definition.qualifier, | ||
definition.primaryType, | ||
), | ||
]?.invoke( | ||
definition.qualifier, | ||
) ?: MockParameter(scope, allParameters.defaultValues) | ||
|
||
logger.info("[Check] definition: $definition") | ||
scope.get<Any>(definition.primaryType, definition.qualifier) { parameters } | ||
|
||
for (secondaryType in definition.secondaryTypes) { | ||
val valueAsSecondary = scope.get<Any>(secondaryType, definition.qualifier) { parameters } | ||
require(secondaryType.isInstance(valueAsSecondary)) { | ||
"instance of ${valueAsSecondary::class} is not inheritable from $secondaryType" | ||
} | ||
} | ||
} |
78 changes: 78 additions & 0 deletions
78
projects/core/koin-test/src/commonMain/kotlin/org/koin/test/check/CheckModulesDSL.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
/* | ||
* Copyright 2017-Present the original author or authors. | ||
* | ||
* 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 org.koin.test.check | ||
|
||
import org.koin.core.Koin | ||
import org.koin.core.parameter.ParametersHolder | ||
import org.koin.core.parameter.parametersOf | ||
import org.koin.core.qualifier.Qualifier | ||
import org.koin.core.qualifier.qualifier | ||
import org.koin.mp.KoinPlatformTools | ||
import org.koin.test.mock.MockProvider | ||
import kotlin.reflect.KClass | ||
|
||
//TODO TO BE DEPRECATED in 3.6 | ||
|
||
@Deprecated("Migrate to verify() API") | ||
data class CheckedComponent(val qualifier: Qualifier? = null, val type: KClass<*>) | ||
|
||
@Deprecated("Migrate to verify() API") | ||
class ParametersBinding(val koin: Koin) { | ||
|
||
val parametersCreators = mutableMapOf<CheckedComponent, ParametersCreator>() | ||
val defaultValues = mutableMapOf<String, Any>() | ||
val scopeLinks = mutableMapOf<Qualifier, Qualifier>() | ||
|
||
@Deprecated("use withParameter() instead", ReplaceWith("withParameters(qualifier,creator)")) | ||
inline fun <reified T> create(qualifier: Qualifier? = null, noinline creator: ParametersCreator) = | ||
parametersCreators.put(CheckedComponent(qualifier, T::class), creator) | ||
|
||
inline fun <reified T> withParameter(qualifier: Qualifier? = null, noinline creator: ParametersInstance) = | ||
parametersCreators.put(CheckedComponent(qualifier, T::class)) { q -> parametersOf(creator(q)) } | ||
|
||
inline fun <reified T> withParameters(qualifier: Qualifier? = null, noinline creator: ParametersCreator) = | ||
parametersCreators.put(CheckedComponent(qualifier, T::class), creator) | ||
|
||
@Deprecated("use withParameter() instead", ReplaceWith("withParameters(clazz,qualifier,creator)")) | ||
fun create(clazz: KClass<*>, qualifier: Qualifier? = null, creator: ParametersCreator) = | ||
parametersCreators.put(CheckedComponent(qualifier, clazz), creator) | ||
|
||
fun withParameter(clazz: KClass<*>, qualifier: Qualifier? = null, creator: ParametersInstance) = | ||
parametersCreators.put(CheckedComponent(qualifier, clazz)) { q -> parametersOf(creator(q)) } | ||
|
||
fun withParameters(clazz: KClass<*>, qualifier: Qualifier? = null, creator: ParametersCreator) = | ||
parametersCreators.put(CheckedComponent(qualifier, clazz), creator) | ||
|
||
@Deprecated("use withInstance() instead", ReplaceWith("withInstance(t)")) | ||
inline fun <reified T : Any> defaultValue(t: T) = defaultValues.put(KoinPlatformTools.getClassName(T::class), t) | ||
|
||
@Deprecated("use withInstance() instead", ReplaceWith("withInstance()")) | ||
inline fun <reified T : Any> defaultValue() = | ||
defaultValues.put(KoinPlatformTools.getClassName(T::class), MockProvider.makeMock<T>()) | ||
|
||
inline fun <reified T : Any> withInstance(t: T) = defaultValues.put(KoinPlatformTools.getClassName(T::class), t) | ||
inline fun <reified T : Any> withInstance() = | ||
defaultValues.put(KoinPlatformTools.getClassName(T::class), MockProvider.makeMock<T>()) | ||
|
||
fun withProperty(key: String, value: Any) = koin.setProperty(key, value) | ||
inline fun <reified T : Any, reified U : Any> withScopeLink() = withScopeLink(qualifier<T>(), qualifier<U>()) | ||
inline fun withScopeLink(scopeQualifier: Qualifier, targetScopeQualifier: Qualifier) = | ||
scopeLinks.put(scopeQualifier, targetScopeQualifier) | ||
} | ||
|
||
typealias ParametersCreator = (Qualifier?) -> ParametersHolder | ||
typealias ParametersInstance = (Qualifier?) -> Any | ||
typealias CheckParameters = ParametersBinding.() -> Unit |
34 changes: 34 additions & 0 deletions
34
projects/core/koin-test/src/jvmTest/kotlin/CheckModulesTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import kotlin.test.Test | ||
import kotlin.test.fail | ||
import org.koin.core.error.InstanceCreationException | ||
import org.koin.dsl.module | ||
import org.koin.test.Simple | ||
import org.koin.test.check.checkKoinModules | ||
import org.koin.test.verify.MissingKoinDefinitionException | ||
|
||
class CheckModulesTest { | ||
|
||
@Test | ||
fun verify_one_simple_module() { | ||
val module = module { | ||
single { Simple.ComponentA() } | ||
single { Simple.ComponentB(get()) } | ||
} | ||
|
||
try { | ||
checkKoinModules(listOf(module)) | ||
} catch (e: MissingKoinDefinitionException) { | ||
fail("Should not fail to verify module - $e") | ||
} | ||
} | ||
|
||
@Test(expected = InstanceCreationException::class) | ||
fun verify_one_simple_broken_module() { | ||
val module = module { | ||
single { Simple.ComponentB(get()) } | ||
} | ||
|
||
checkKoinModules(listOf(module)) | ||
fail("Should fail to verify module") | ||
} | ||
} |
8 changes: 2 additions & 6 deletions
8
projects/core/koin-test/src/jvmTest/kotlin/VerifyModulesTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters