From e7b495b0ce1a89ea265d617afd70d9932c578c06 Mon Sep 17 00:00:00 2001 From: Egor Kulikov Date: Wed, 31 May 2023 16:18:31 +0300 Subject: [PATCH 1/2] Correct two regressions in Spring codegen --- .../services/framework/MockFrameworkManager.kt | 10 +++------- .../tree/CgSpringUnitTestClassConstructor.kt | 17 +++++++++++++---- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/services/framework/MockFrameworkManager.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/services/framework/MockFrameworkManager.kt index 6145ebdcf5..e3422a096b 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/services/framework/MockFrameworkManager.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/services/framework/MockFrameworkManager.kt @@ -183,8 +183,6 @@ private abstract class StaticMocker( private class MockitoMocker(context: CgContext) : ObjectMocker(context) { - private val alreadyMockedModels: MutableSet = Collections.newSetFromMap(IdentityHashMap()) - override fun createMock(model: UtCompositeModel, baseName: String): CgVariable { val modelClass = getClassOf(model.classId) val mockObject = newVar(model.classId, baseName = baseName, isMock = true) { mock(modelClass) } @@ -195,10 +193,6 @@ private class MockitoMocker(context: CgContext) : ObjectMocker(context) { } fun mockForVariable(model: UtCompositeModel, mockObject: CgVariable) { - if (!alreadyMockedModels.add(model)) { - return - } - for ((executable, values) in model.mocks) { val matchers = mockitoArgumentMatchersFor(executable) @@ -225,7 +219,9 @@ private class MockitoMocker(context: CgContext) : ObjectMocker(context) { error("Cannot mock method $executable as it is not accessible from package $testClassPackageName") } - val results = values.map { variableConstructor.getOrCreateVariable(it) }.toTypedArray() + val results = values + .map { if (it === model) mockObject else variableConstructor.getOrCreateVariable(it) } + .toTypedArray() `when`(mockObject[executable](*matchers)).thenReturn(executable.returnType, *results) } else -> error("Only MethodId was expected to appear in simple mocker but got $executable") diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgSpringUnitTestClassConstructor.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgSpringUnitTestClassConstructor.kt index a0fd564098..e5fe953f12 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgSpringUnitTestClassConstructor.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgSpringUnitTestClassConstructor.kt @@ -21,23 +21,32 @@ import org.utbot.framework.plugin.api.util.objectClassId class CgSpringUnitTestClassConstructor(context: CgContext) : CgAbstractSpringTestClassConstructor(context) { + private var additionalMethodsRequired: Boolean = false + private lateinit var mockitoCloseableVariable: CgValue override fun constructClassFields(testClassModel: SpringTestClassModel): List { val fields = mutableListOf() - val mockedFields = constructFieldsWithAnnotation(testClassModel.thisInstanceDependentMocks, mockClassId) - if (mockedFields.isNotEmpty()) { - fields += constructFieldsWithAnnotation(testClassModel.thisInstanceModels, injectMocksClassId) - fields += mockedFields + if (testClassModel.thisInstanceDependentMocks.isNotEmpty()) { + val mockedFields = constructFieldsWithAnnotation(testClassModel.thisInstanceDependentMocks, mockClassId) + val injectingMocksFields = constructFieldsWithAnnotation(testClassModel.thisInstanceModels, injectMocksClassId) + fields += injectingMocksFields + fields += mockedFields fields += constructMockitoCloseables() } + additionalMethodsRequired = fields.isNotEmpty() + return fields } override fun constructAdditionalMethods(): CgMethodsCluster { + if (!additionalMethodsRequired) { + return CgMethodsCluster(header = null, content = emptyList(),) + } + importIfNeeded(openMocksMethodId) val openMocksCall = CgMethodCall( From 1d34ce324940960c8638c0ebdaf8bf3e4a73ec5f Mon Sep 17 00:00:00 2001 From: Egor Kulikov Date: Wed, 31 May 2023 16:46:52 +0300 Subject: [PATCH 2/2] Little corrections --- .../codegen/services/framework/MockFrameworkManager.kt | 5 ++++- .../codegen/tree/CgSpringUnitTestClassConstructor.kt | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/services/framework/MockFrameworkManager.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/services/framework/MockFrameworkManager.kt index e3422a096b..95c2fc4518 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/services/framework/MockFrameworkManager.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/services/framework/MockFrameworkManager.kt @@ -220,7 +220,10 @@ private class MockitoMocker(context: CgContext) : ObjectMocker(context) { } val results = values - .map { if (it === model) mockObject else variableConstructor.getOrCreateVariable(it) } + .map { value -> + // Sometimes we need mocks returning itself, e.g. for StringBuilder.append method + if (value != model) variableConstructor.getOrCreateVariable(value) else mockObject + } .toTypedArray() `when`(mockObject[executable](*matchers)).thenReturn(executable.returnType, *results) } diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgSpringUnitTestClassConstructor.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgSpringUnitTestClassConstructor.kt index e5fe953f12..25474ed26b 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgSpringUnitTestClassConstructor.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgSpringUnitTestClassConstructor.kt @@ -35,9 +35,9 @@ class CgSpringUnitTestClassConstructor(context: CgContext) : CgAbstractSpringTes fields += injectingMocksFields fields += mockedFields fields += constructMockitoCloseables() - } - additionalMethodsRequired = fields.isNotEmpty() + additionalMethodsRequired = true + } return fields }