@@ -22,7 +22,6 @@ import org.utbot.framework.codegen.domain.context.CgContext
22
22
import org.utbot.framework.codegen.domain.context.CgContextOwner
23
23
import org.utbot.framework.codegen.domain.models.CgAnonymousFunction
24
24
import org.utbot.framework.codegen.domain.models.CgAssignment
25
- import org.utbot.framework.codegen.domain.models.CgBreakStatement
26
25
import org.utbot.framework.codegen.domain.models.CgConstructorCall
27
26
import org.utbot.framework.codegen.domain.models.CgDeclaration
28
27
import org.utbot.framework.codegen.domain.models.CgExecutableCall
@@ -232,7 +231,12 @@ private class MockitoStaticMocker(context: CgContext, private val mocker: Object
232
231
.instances
233
232
.filterIsInstance<UtCompositeModel >()
234
233
.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
+ }
236
240
237
241
val modelClass = getClassOf(classId)
238
242
@@ -248,6 +252,8 @@ private class MockitoStaticMocker(context: CgContext, private val mocker: Object
248
252
+ mockClassCounter
249
253
}
250
254
255
+ // TODO this behavior diverges with expected by the symbolic engine,
256
+ // see https://github.com/UnitTestBot/UTBotJava/issues/1953 for more details
251
257
val mockedConstructionDeclaration = CgDeclaration (
252
258
MockitoStaticMocking .mockedConstructionClassId,
253
259
nameGenerator.variableName(MOCKED_CONSTRUCTION_NAME ),
@@ -276,10 +282,10 @@ private class MockitoStaticMocker(context: CgContext, private val mocker: Object
276
282
listOf (
277
283
CgStatementExecutableCall (
278
284
CgMethodCall (
279
- caller = null ,
280
- methodId,
281
- matchers.toList()
282
- )
285
+ caller = null ,
286
+ methodId,
287
+ matchers.toList()
288
+ )
283
289
)
284
290
)
285
291
)
@@ -328,21 +334,29 @@ private class MockitoStaticMocker(context: CgContext, private val mocker: Object
328
334
): MockConstructionBlock {
329
335
val mockParameter = variableConstructor.declareParameter(
330
336
classId,
331
- nameGenerator.variableName(classId.simpleName, isMock = true )
337
+ nameGenerator.variableName(
338
+ classId,
339
+ isMock = true
340
+ )
332
341
)
333
342
val contextParameter = variableConstructor.declareParameter(
334
343
mockedConstructionContextClassId,
335
344
nameGenerator.variableName(" context" )
336
345
)
337
346
338
- val caseLabels = mutableListOf<CgSwitchCaseLabel >()
347
+ val mockAnswerStatements = mutableMapOf<Int , List <CgStatement >>()
348
+
339
349
for ((index, mockWhenAnswers) in mocksWhenAnswers.withIndex()) {
340
350
val statements = mutableListOf<CgStatement >()
341
351
for ((executable, values) in mockWhenAnswers) {
342
352
// For now, all constructors are considered like void methods, but it is proposed to be changed
343
353
// for better constructors testing.
344
354
if (executable.returnType == voidClassId) continue
345
355
356
+ require(values.isNotEmpty()) {
357
+ " Expected at least one mocked answer for $executable but got 0"
358
+ }
359
+
346
360
when (executable) {
347
361
is MethodId -> {
348
362
val matchers = mockitoArgumentMatchersFor(executable)
@@ -355,16 +369,21 @@ private class MockitoStaticMocker(context: CgContext, private val mocker: Object
355
369
}
356
370
}
357
371
358
- caseLabels + = CgSwitchCaseLabel ( CgLiteral (intClassId, index), statements)
372
+ mockAnswerStatements[index] = statements
359
373
}
360
374
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,
364
377
// 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()
367
381
} else {
382
+ val caseLabels = mockAnswerStatements.map { (index, statements) ->
383
+ CgSwitchCaseLabel (CgLiteral (intClassId, index), statements)
384
+ }
385
+ val switchCase = CgSwitchCase (mockClassCounter[atomicIntegerGet](), caseLabels)
386
+
368
387
listOf (switchCase, CgStatementExecutableCall (mockClassCounter[atomicIntegerGetAndIncrement]()))
369
388
}
370
389
@@ -376,7 +395,7 @@ private class MockitoStaticMocker(context: CgContext, private val mocker: Object
376
395
377
396
return MockConstructionBlock (
378
397
mockitoClassId[MockitoStaticMocking .mockConstructionMethodId](clazz, answersBlock),
379
- mockConstructionBody.isNotEmpty()
398
+ ! atMostOneBranchOrAllEmpty
380
399
)
381
400
}
382
401
0 commit comments