Skip to content

Commit 00061a7

Browse files
committed
Removed unnecessary mock counter and corresponding switch when mocking constructors
1 parent 8fb6764 commit 00061a7

File tree

3 files changed

+41
-11
lines changed

3 files changed

+41
-11
lines changed

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/domain/models/CgElement.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -888,7 +888,7 @@ class CgIfStatement(
888888

889889
data class CgSwitchCaseLabel(
890890
val label: CgLiteral? = null, // have to be compile time constant (null for default label)
891-
val statements: MutableList<CgStatement>
891+
val statements: List<CgStatement>
892892
) : CgStatement
893893

894894
data class CgSwitchCase(

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/renderer/CgJavaRenderer.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,8 +314,6 @@ internal class CgJavaRenderer(context: CgRendererContext, printer: CgPrinter = C
314314
for (statement in element.statements) {
315315
statement.accept(this)
316316
}
317-
// break statement in the end
318-
CgBreakStatement.accept(this)
319317
}
320318
}
321319

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/services/framework/MockFrameworkManager.kt

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import org.utbot.framework.codegen.domain.context.CgContext
2222
import org.utbot.framework.codegen.domain.context.CgContextOwner
2323
import org.utbot.framework.codegen.domain.models.CgAnonymousFunction
2424
import org.utbot.framework.codegen.domain.models.CgAssignment
25+
import org.utbot.framework.codegen.domain.models.CgBreakStatement
2526
import org.utbot.framework.codegen.domain.models.CgConstructorCall
2627
import org.utbot.framework.codegen.domain.models.CgDeclaration
2728
import org.utbot.framework.codegen.domain.models.CgExecutableCall
@@ -226,7 +227,6 @@ private class MockitoStaticMocker(context: CgContext, private val mocker: Object
226227
nameGenerator.variableName(MOCK_CLASS_COUNTER_NAME),
227228
CgConstructorCall(ConstructorId(atomicIntegerClassId, emptyList()), emptyList())
228229
)
229-
+mockClassCounter
230230

231231
val mocksExecutablesAnswers = mock
232232
.instances
@@ -242,13 +242,19 @@ private class MockitoStaticMocker(context: CgContext, private val mocker: Object
242242
mocksExecutablesAnswers,
243243
mockClassCounter.variable
244244
)
245+
246+
if (mockConstructionInitializer.isMockClassCounterRequired) {
247+
// We should insert the counter declaration only if we use this counter, for better readability.
248+
+mockClassCounter
249+
}
250+
245251
val mockedConstructionDeclaration = CgDeclaration(
246252
MockitoStaticMocking.mockedConstructionClassId,
247253
nameGenerator.variableName(MOCKED_CONSTRUCTION_NAME),
248-
mockConstructionInitializer
254+
mockConstructionInitializer.mockConstructionCall
249255
)
250256
resources += mockedConstructionDeclaration
251-
+CgAssignment(mockedConstructionDeclaration.variable, mockConstructionInitializer)
257+
+CgAssignment(mockedConstructionDeclaration.variable, mockConstructionInitializer.mockConstructionCall)
252258
mockedStaticConstructions += classId
253259
}
254260

@@ -317,9 +323,9 @@ private class MockitoStaticMocker(context: CgContext, private val mocker: Object
317323
private fun mockConstruction(
318324
clazz: CgExpression,
319325
classId: ClassId,
320-
mocksWhenAnswers: List<MutableMap<ExecutableId, List<UtModel>>>,
326+
mocksWhenAnswers: List<Map<ExecutableId, List<UtModel>>>,
321327
mockClassCounter: CgVariable
322-
): CgMethodCall {
328+
): MockConstructionBlock {
323329
val mockParameter = variableConstructor.declareParameter(
324330
classId,
325331
nameGenerator.variableName(classId.simpleName, isMock = true)
@@ -333,6 +339,8 @@ private class MockitoStaticMocker(context: CgContext, private val mocker: Object
333339
for ((index, mockWhenAnswers) in mocksWhenAnswers.withIndex()) {
334340
val statements = mutableListOf<CgStatement>()
335341
for ((executable, values) in mockWhenAnswers) {
342+
// For now, all constructors are considered like void methods, but it is proposed to be changed
343+
// for better constructors testing.
336344
if (executable.returnType == voidClassId) continue
337345

338346
when (executable) {
@@ -343,24 +351,48 @@ private class MockitoStaticMocker(context: CgContext, private val mocker: Object
343351
mocker.`when`(mockParameter[executable](*matchers))[thenReturnMethodId](*results)
344352
)
345353
}
346-
else -> error("Expected MethodId but got ConstructorId $executable")
354+
is ConstructorId -> error("Expected MethodId but got ConstructorId $executable")
347355
}
348356
}
349357

358+
// Always add "break" statement to prevent fall-through.
359+
statements += CgBreakStatement
360+
350361
caseLabels += CgSwitchCaseLabel(CgLiteral(intClassId, index), statements)
351362
}
352363

353364
val switchCase = CgSwitchCase(mockClassCounter[atomicIntegerGet](), caseLabels)
354365

366+
// If all switch-case labels contain only break statements,
367+
// it means we do not need this switch and mock counter itself at all.
368+
val mockConstructionBody = if (caseLabels.map { it.statements }.all { it.singleOrNull() is CgBreakStatement }) {
369+
emptyList()
370+
} else {
371+
listOf(switchCase, CgStatementExecutableCall(mockClassCounter[atomicIntegerGetAndIncrement]()))
372+
}
373+
355374
val answersBlock = CgAnonymousFunction(
356375
voidClassId,
357376
listOf(mockParameter, contextParameter).map { CgParameterDeclaration(it, isVararg = false) },
358-
listOf(switchCase, CgStatementExecutableCall(mockClassCounter[atomicIntegerGetAndIncrement]()))
377+
mockConstructionBody
359378
)
360379

361-
return mockitoClassId[MockitoStaticMocking.mockConstructionMethodId](clazz, answersBlock)
380+
return MockConstructionBlock(
381+
mockitoClassId[MockitoStaticMocking.mockConstructionMethodId](clazz, answersBlock),
382+
mockConstructionBody.isNotEmpty()
383+
)
362384
}
363385

386+
/**
387+
* Represents a body for invocation of the [MockitoStaticMocking.mockConstructionMethodId] method and information
388+
* whether we need to use a counter for different mocking invocations
389+
* (i.e., on each mocking we expect possibly different results).
390+
*/
391+
private data class MockConstructionBlock(
392+
val mockConstructionCall: CgMethodCall,
393+
val isMockClassCounterRequired: Boolean
394+
)
395+
364396
private fun mockStatic(clazz: CgExpression): CgMethodCall =
365397
mockitoClassId[MockitoStaticMocking.mockStaticMethodId](clazz)
366398

0 commit comments

Comments
 (0)