[Test] Don't override manually registered services during test configuration

There are two ways of test service registration:
- manual call to `useAdditionalServices` in abstract test runner
- using of `additionalServices` property in one of test entity (e.g. in handler)

Services are registered in the same order (manual first, automatic second)

This led to the situation that if there was registered more specific
  implementation of the service in the test configuration, it will be
  overridden with regular implementation from handler, which is fixed
  by this commit
This commit is contained in:
Dmitriy Novozhilov
2024-01-10 10:52:07 +02:00
committed by Nikolay Lunyak
parent 990da9fa1a
commit cb3f41f669
3 changed files with 17 additions and 6 deletions
@@ -39,7 +39,10 @@ class TestServices : ComponentArrayOwner<TestService, TestService>(){
}
}
fun register(data: ServiceRegistrationData) {
fun register(data: ServiceRegistrationData, skipAlreadyRegistered: Boolean) {
if (skipAlreadyRegistered && getOrNull(data.kClass) != null) {
return
}
registerComponent(data.kClass, data.serviceConstructor(this))
}
@@ -47,8 +50,8 @@ class TestServices : ComponentArrayOwner<TestService, TestService>(){
registerComponent(kClass, service)
}
fun register(data: List<ServiceRegistrationData>) {
data.forEach { register(it) }
fun register(data: List<ServiceRegistrationData>, skipAlreadyRegistered: Boolean) {
data.forEach { register(it, skipAlreadyRegistered) }
}
}
@@ -58,7 +58,9 @@ class TestConfigurationImpl(
testServices.register(KotlinTestInfo::class, testInfo)
val runtimeClassPathProviders = runtimeClasspathProviders.map { it.invoke(testServices) }
testServices.register(RuntimeClasspathProvidersContainer::class, RuntimeClasspathProvidersContainer(runtimeClassPathProviders))
additionalServices.forEach { testServices.register(it) }
additionalServices.forEach {
testServices.register(it, skipAlreadyRegistered = false)
}
}
private val allDirectives = directives.toMutableSet()
@@ -131,7 +133,7 @@ class TestConfigurationImpl(
private fun ServicesAndDirectivesContainer.registerDirectivesAndServices() {
allDirectives += directiveContainers
testServices.register(additionalServices)
testServices.register(additionalServices, skipAlreadyRegistered = true)
}
private fun List<ServicesAndDirectivesContainer>.registerDirectivesAndServices() {
@@ -25,8 +25,14 @@ abstract class ComponentArrayOwner<K : Any, V : Any> : AbstractArrayMapOwner<K,
}
protected operator fun get(key: KClass<out K>): V {
getOrNull(key)?.let { return it }
val id = typeRegistry.getId(key)
return arrayMap[id] ?: error("No '$key'($id) component in array: $this")
error("No '$key'($id) component in array: $this")
}
protected fun getOrNull(key: KClass<out K>): V? {
val id = typeRegistry.getId(key)
return arrayMap[id]
}
private fun createDiagnosticMessage(id: Int, keyQualifiedName: String): String = buildString {