From 89d23f053b42cb927d1f09840068c63a286396db Mon Sep 17 00:00:00 2001 From: Egor Kulikov Date: Tue, 25 Jul 2023 02:01:08 +0300 Subject: [PATCH] Remove unnecessary annotations from Spring integration tests --- .../org/utbot/framework/plugin/api/Api.kt | 7 +- ...CgSpringIntegrationTestClassConstructor.kt | 89 ++++++++++--------- .../spring/SpringInstrumentationContext.kt | 2 +- .../generator/UtTestsDialogProcessor.kt | 6 +- .../plugin/ui/GenerateTestsDialogWindow.kt | 11 ++- .../org/utbot/spring/utils/SourceFinder.kt | 5 +- 6 files changed, 68 insertions(+), 52 deletions(-) diff --git a/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/Api.kt b/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/Api.kt index 9ff4eebed3..cd6c36939e 100644 --- a/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/Api.kt +++ b/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/Api.kt @@ -1320,7 +1320,12 @@ enum class TypeReplacementMode { } sealed class SpringConfiguration(val fullDisplayName: String) { - class JavaConfiguration(val classBinaryName: String) : SpringConfiguration(classBinaryName) + abstract class JavaBasedConfiguration(open val configBinaryName: String) : SpringConfiguration(configBinaryName) + + class JavaConfiguration(override val configBinaryName: String) : JavaBasedConfiguration(configBinaryName) + + class SpringBootConfiguration(override val configBinaryName: String, val isUnique: Boolean): JavaBasedConfiguration(configBinaryName) + class XMLConfiguration(val absolutePath: String) : SpringConfiguration(absolutePath) } diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgSpringIntegrationTestClassConstructor.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgSpringIntegrationTestClassConstructor.kt index 4935c85ee4..743f6114ed 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgSpringIntegrationTestClassConstructor.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgSpringIntegrationTestClassConstructor.kt @@ -103,6 +103,11 @@ class CgSpringIntegrationTestClassConstructor( ) private fun addNecessarySpringSpecificAnnotations() { + val isSpringBootTestAccessible = utContext.classLoader.tryLoadClass(springBootTestClassId.name) != null + if (isSpringBootTestAccessible) { + addAnnotation(springBootTestClassId, Class) + } + val (testFrameworkExtension, springExtension) = when (testFramework) { Junit4 -> runWithClassId to springRunnerClassId Junit5 -> extendWithClassId to springExtensionClassId @@ -110,11 +115,14 @@ class CgSpringIntegrationTestClassConstructor( else -> error("Trying to generate tests for Spring project with non-JVM framework") } - addAnnotation( - classId = testFrameworkExtension, - argument = createGetClassExpression(springExtension, codegenLanguage), - target = Class, - ) + // @SpringBootTest contains @ExtendWith(SpringExtension.class), no need to add it manually + if (!isSpringBootTestAccessible || testFrameworkExtension != extendWithClassId) { + addAnnotation( + classId = testFrameworkExtension, + argument = createGetClassExpression(springExtension, codegenLanguage), + target = Class, + ) + } if (utContext.classLoader.tryLoadClass(springBootTestContextBootstrapperClassId.name) != null) // TODO in somewhat new versions of Spring Boot, @SpringBootTest @@ -126,49 +134,44 @@ class CgSpringIntegrationTestClassConstructor( target = Class, ) - if (utContext.classLoader.tryLoadClass(springBootTestClassId.name) != null) - addAnnotation(springBootTestClassId, Class) - - // TODO avoid adding @ActiveProfiles(profiles = {"default"}) to reduce number of annotations - addAnnotation( - classId = activeProfilesClassId, - namedArguments = - listOf( - CgNamedAnnotationArgument( - name = "profiles", - value = - CgArrayAnnotationArgument( - springSettings.profiles.map { profile -> - profile.resolve() - } + val defaultProfileIsUsed = springSettings.profiles.singleOrNull() == "default" + if (!defaultProfileIsUsed) { + addAnnotation( + classId = activeProfilesClassId, + namedArguments = listOf( + CgNamedAnnotationArgument( + name = "profiles", + value = CgArrayAnnotationArgument(springSettings.profiles.map { profile -> profile.resolve() }) ) - ) - ), - target = Class, - ) + ), + target = Class, + ) + } - // TODO avoid adding @ContextConfiguration(classes = {$defaultBootConfigClass}) to reduce number of annotations - addAnnotation( - classId = contextConfigurationClassId, - namedArguments = - listOf( - CgNamedAnnotationArgument( - name = "classes", - value = CgArrayAnnotationArgument( - listOf( - createGetClassExpression( - // TODO: - // For now we support only JavaConfigurations in integration tests. - // Adapt for XMLConfigurations when supported. - ClassId((springSettings.configuration as JavaConfiguration).classBinaryName), - codegenLanguage + val configClass = springSettings.configuration as JavaBasedConfiguration + if (configClass is JavaConfiguration || configClass is SpringBootConfiguration && !configClass.isUnique) { + addAnnotation( + classId = contextConfigurationClassId, + namedArguments = listOf( + CgNamedAnnotationArgument( + name = "classes", + value = CgArrayAnnotationArgument( + listOf( + createGetClassExpression( + // TODO: we support only JavaConfigurations in integration tests. + // Adapt for XMLConfigurations when supported. + ClassId((springSettings.configuration as JavaConfiguration).configBinaryName), + codegenLanguage + ) ) ) ) - ) - ), - target = Class, - ) + ), + target = Class, + ) + } + + addAnnotation( classId = dirtiesContextClassId, namedArguments = listOf( diff --git a/utbot-instrumentation/src/main/kotlin/org/utbot/instrumentation/instrumentation/spring/SpringInstrumentationContext.kt b/utbot-instrumentation/src/main/kotlin/org/utbot/instrumentation/instrumentation/spring/SpringInstrumentationContext.kt index eaf119b571..6850a0e67a 100644 --- a/utbot-instrumentation/src/main/kotlin/org/utbot/instrumentation/instrumentation/spring/SpringInstrumentationContext.kt +++ b/utbot-instrumentation/src/main/kotlin/org/utbot/instrumentation/instrumentation/spring/SpringInstrumentationContext.kt @@ -26,7 +26,7 @@ class SpringInstrumentationContext( // so we expect JavaConfigurations only. // After fix rewrite the following. classLoader.loadClass( - (springSettings.configuration as? JavaConfiguration)?.classBinaryName + (springSettings.configuration as? JavaBasedConfiguration)?.configBinaryName ?: error("JavaConfiguration was expected, but ${springSettings.configuration.javaClass.name} was provided.") ) ), diff --git a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/generator/UtTestsDialogProcessor.kt b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/generator/UtTestsDialogProcessor.kt index 87e0da4865..99ead38d0b 100644 --- a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/generator/UtTestsDialogProcessor.kt +++ b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/generator/UtTestsDialogProcessor.kt @@ -180,10 +180,10 @@ object UtTestsDialogProcessor { is AbsentSpringSettings -> null is PresentSpringSettings -> when (val config = settings.configuration) { - is JavaConfiguration -> { + is JavaBasedConfiguration -> { PsiClassHelper - .findClass(config.classBinaryName, project) - ?: error("Cannot find configuration class ${config.classBinaryName}.") + .findClass(config.configBinaryName, project) + ?: error("Cannot find configuration class ${config.configBinaryName}.") } // TODO: for XML config we also need to compile module containing, // since it may reference classes from that module diff --git a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/GenerateTestsDialogWindow.kt b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/GenerateTestsDialogWindow.kt index 547ab7090b..f61093eee2 100644 --- a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/GenerateTestsDialogWindow.kt +++ b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/GenerateTestsDialogWindow.kt @@ -703,7 +703,16 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m SpringConfiguration.XMLConfiguration(absolutePath) } else { val classBinaryName = javaConfigurationHelper.restoreFullName(shortConfigName) - SpringConfiguration.JavaConfiguration(classBinaryName) + + val springBootConfigs = model.getSortedSpringBootApplicationClasses() + if (springBootConfigs.contains(classBinaryName)) { + SpringConfiguration.SpringBootConfiguration( + configBinaryName = classBinaryName, + isUnique = springBootConfigs.size == 1, + ) + } else { + SpringConfiguration.JavaConfiguration(classBinaryName) + } } PresentSpringSettings( diff --git a/utbot-spring-analyzer/src/main/kotlin/org/utbot/spring/utils/SourceFinder.kt b/utbot-spring-analyzer/src/main/kotlin/org/utbot/spring/utils/SourceFinder.kt index 691ce2f40c..027dabbdc5 100644 --- a/utbot-spring-analyzer/src/main/kotlin/org/utbot/spring/utils/SourceFinder.kt +++ b/utbot-spring-analyzer/src/main/kotlin/org/utbot/spring/utils/SourceFinder.kt @@ -7,7 +7,6 @@ import org.utbot.common.patchAnnotation import org.utbot.framework.plugin.api.SpringConfiguration.* import org.utbot.spring.api.ApplicationData import org.utbot.spring.config.TestApplicationConfiguration -import org.utbot.spring.configurators.ApplicationConfigurationType import java.nio.file.Path import kotlin.io.path.Path @@ -20,11 +19,11 @@ class SourceFinder( fun findSources(): Array> = when (val config = applicationData.springSettings.configuration) { - is JavaConfiguration -> { + is JavaBasedConfiguration -> { logger.info { "Using java Spring configuration" } arrayOf( TestApplicationConfiguration::class.java, - classLoader.loadClass(config.classBinaryName) + classLoader.loadClass(config.configBinaryName) ) }