@@ -22,7 +22,6 @@ import org.utbot.framework.codegen.domain.context.CgContext
2222import org.utbot.framework.codegen.domain.context.CgContextOwner
2323import org.utbot.framework.codegen.domain.models.CgAnonymousFunction
2424import org.utbot.framework.codegen.domain.models.CgAssignment
25- import org.utbot.framework.codegen.domain.models.CgBreakStatement
2625import org.utbot.framework.codegen.domain.models.CgConstructorCall
2726import org.utbot.framework.codegen.domain.models.CgDeclaration
2827import org.utbot.framework.codegen.domain.models.CgExecutableCall
@@ -232,7 +231,12 @@ private class MockitoStaticMocker(context: CgContext, private val mocker: Object
232231 .instances
233232 .filterIsInstance<UtCompositeModel >()
234233 .filter { it.isMock }
235- .map { it.mocks }
234+ .map {
235+ // If there are no expected answers for the particular executable
236+ // (this executable is never invoked during the execution, for example),
237+ // we do not need to consider this executable at all.
238+ it.mocks.filterTo(mutableMapOf ()) { executableAnswers -> executableAnswers.value.isNotEmpty() }
239+ }
236240
237241 val modelClass = getClassOf(classId)
238242
@@ -248,6 +252,8 @@ private class MockitoStaticMocker(context: CgContext, private val mocker: Object
248252 + mockClassCounter
249253 }
250254
255+ // TODO this behavior diverges with expected by the symbolic engine,
256+ // see https://github.com/UnitTestBot/UTBotJava/issues/1953 for more details
251257 val mockedConstructionDeclaration = CgDeclaration (
252258 MockitoStaticMocking .mockedConstructionClassId,
253259 nameGenerator.variableName(MOCKED_CONSTRUCTION_NAME ),
@@ -276,10 +282,10 @@ private class MockitoStaticMocker(context: CgContext, private val mocker: Object
276282 listOf (
277283 CgStatementExecutableCall (
278284 CgMethodCall (
279- caller = null ,
280- methodId,
281- matchers.toList()
282- )
285+ caller = null ,
286+ methodId,
287+ matchers.toList()
288+ )
283289 )
284290 )
285291 )
@@ -328,21 +334,29 @@ private class MockitoStaticMocker(context: CgContext, private val mocker: Object
328334 ): MockConstructionBlock {
329335 val mockParameter = variableConstructor.declareParameter(
330336 classId,
331- nameGenerator.variableName(classId.simpleName, isMock = true )
337+ nameGenerator.variableName(
338+ classId,
339+ isMock = true
340+ )
332341 )
333342 val contextParameter = variableConstructor.declareParameter(
334343 mockedConstructionContextClassId,
335344 nameGenerator.variableName(" context" )
336345 )
337346
338- val caseLabels = mutableListOf<CgSwitchCaseLabel >()
347+ val mockAnswerStatements = mutableMapOf<Int , List <CgStatement >>()
348+
339349 for ((index, mockWhenAnswers) in mocksWhenAnswers.withIndex()) {
340350 val statements = mutableListOf<CgStatement >()
341351 for ((executable, values) in mockWhenAnswers) {
342352 // For now, all constructors are considered like void methods, but it is proposed to be changed
343353 // for better constructors testing.
344354 if (executable.returnType == voidClassId) continue
345355
356+ require(values.isNotEmpty()) {
357+ " Expected at least one mocked answer for $executable but got 0"
358+ }
359+
346360 when (executable) {
347361 is MethodId -> {
348362 val matchers = mockitoArgumentMatchersFor(executable)
@@ -355,16 +369,21 @@ private class MockitoStaticMocker(context: CgContext, private val mocker: Object
355369 }
356370 }
357371
358- caseLabels + = CgSwitchCaseLabel ( CgLiteral (intClassId, index), statements)
372+ mockAnswerStatements[index] = statements
359373 }
360374
361- val switchCase = CgSwitchCase (mockClassCounter[atomicIntegerGet](), caseLabels)
362-
363- // If all switch-case labels are empty,
375+ val answerValues = mockAnswerStatements.values
376+ // If we have no more than one branch or all branches are empty,
364377 // it means we do not need this switch and mock counter itself at all.
365- val mockConstructionBody = if (caseLabels.map { it.statements }.all { it.isEmpty() }) {
366- emptyList()
378+ val atMostOneBranchOrAllEmpty = answerValues.size <= 1 || answerValues.all { statements -> statements.isEmpty() }
379+ val mockConstructionBody = if (atMostOneBranchOrAllEmpty) {
380+ answerValues.singleOrNull() ? : emptyList()
367381 } else {
382+ val caseLabels = mockAnswerStatements.map { (index, statements) ->
383+ CgSwitchCaseLabel (CgLiteral (intClassId, index), statements)
384+ }
385+ val switchCase = CgSwitchCase (mockClassCounter[atomicIntegerGet](), caseLabels)
386+
368387 listOf (switchCase, CgStatementExecutableCall (mockClassCounter[atomicIntegerGetAndIncrement]()))
369388 }
370389
@@ -376,7 +395,7 @@ private class MockitoStaticMocker(context: CgContext, private val mocker: Object
376395
377396 return MockConstructionBlock (
378397 mockitoClassId[MockitoStaticMocking .mockConstructionMethodId](clazz, answersBlock),
379- mockConstructionBody.isNotEmpty()
398+ ! atMostOneBranchOrAllEmpty
380399 )
381400 }
382401
0 commit comments