Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import org.utbot.framework.codegen.domain.context.CgContext
import org.utbot.framework.codegen.domain.context.CgContextOwner
import org.utbot.framework.codegen.domain.models.CgAnonymousFunction
import org.utbot.framework.codegen.domain.models.CgAssignment
import org.utbot.framework.codegen.domain.models.CgBreakStatement
import org.utbot.framework.codegen.domain.models.CgConstructorCall
import org.utbot.framework.codegen.domain.models.CgDeclaration
import org.utbot.framework.codegen.domain.models.CgExecutableCall
Expand Down Expand Up @@ -232,7 +231,12 @@ private class MockitoStaticMocker(context: CgContext, private val mocker: Object
.instances
.filterIsInstance<UtCompositeModel>()
.filter { it.isMock }
.map { it.mocks }
.map {
// If there are no expected answers for the particular executable
// (this executable is never invoked during the execution, for example),
// we do not need to consider this executable at all.
it.mocks.filterTo(mutableMapOf()) { executableAnswers -> executableAnswers.value.isNotEmpty() }
}

val modelClass = getClassOf(classId)

Expand All @@ -248,6 +252,8 @@ private class MockitoStaticMocker(context: CgContext, private val mocker: Object
+mockClassCounter
}

// TODO this behavior diverges with expected by the symbolic engine,
// see https://github.com/UnitTestBot/UTBotJava/issues/1953 for more details
val mockedConstructionDeclaration = CgDeclaration(
MockitoStaticMocking.mockedConstructionClassId,
nameGenerator.variableName(MOCKED_CONSTRUCTION_NAME),
Expand Down Expand Up @@ -276,10 +282,10 @@ private class MockitoStaticMocker(context: CgContext, private val mocker: Object
listOf(
CgStatementExecutableCall(
CgMethodCall(
caller = null,
methodId,
matchers.toList()
)
caller = null,
methodId,
matchers.toList()
)
)
)
)
Expand Down Expand Up @@ -328,21 +334,29 @@ private class MockitoStaticMocker(context: CgContext, private val mocker: Object
): MockConstructionBlock {
val mockParameter = variableConstructor.declareParameter(
classId,
nameGenerator.variableName(classId.simpleName, isMock = true)
nameGenerator.variableName(
classId,
isMock = true
)
)
val contextParameter = variableConstructor.declareParameter(
mockedConstructionContextClassId,
nameGenerator.variableName("context")
)

val caseLabels = mutableListOf<CgSwitchCaseLabel>()
val mockAnswerStatements = mutableMapOf<Int, List<CgStatement>>()

for ((index, mockWhenAnswers) in mocksWhenAnswers.withIndex()) {
val statements = mutableListOf<CgStatement>()
for ((executable, values) in mockWhenAnswers) {
// For now, all constructors are considered like void methods, but it is proposed to be changed
// for better constructors testing.
if (executable.returnType == voidClassId) continue

require(values.isNotEmpty()) {
"Expected at least one mocked answer for $executable but got 0"
}

when (executable) {
is MethodId -> {
val matchers = mockitoArgumentMatchersFor(executable)
Expand All @@ -355,16 +369,21 @@ private class MockitoStaticMocker(context: CgContext, private val mocker: Object
}
}

caseLabels += CgSwitchCaseLabel(CgLiteral(intClassId, index), statements)
mockAnswerStatements[index] = statements
}

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

// If all switch-case labels are empty,
val answerValues = mockAnswerStatements.values
// If we have no more than one branch or all branches are empty,
// it means we do not need this switch and mock counter itself at all.
val mockConstructionBody = if (caseLabels.map { it.statements }.all { it.isEmpty() }) {
emptyList()
val atMostOneBranchOrAllEmpty = answerValues.size <= 1 || answerValues.all { statements -> statements.isEmpty() }
val mockConstructionBody = if (atMostOneBranchOrAllEmpty) {
answerValues.singleOrNull() ?: emptyList()
} else {
val caseLabels = mockAnswerStatements.map { (index, statements) ->
CgSwitchCaseLabel(CgLiteral(intClassId, index), statements)
}
val switchCase = CgSwitchCase(mockClassCounter[atomicIntegerGet](), caseLabels)

listOf(switchCase, CgStatementExecutableCall(mockClassCounter[atomicIntegerGetAndIncrement]()))
}

Expand All @@ -376,7 +395,7 @@ private class MockitoStaticMocker(context: CgContext, private val mocker: Object

return MockConstructionBlock(
mockitoClassId[MockitoStaticMocking.mockConstructionMethodId](clazz, answersBlock),
mockConstructionBody.isNotEmpty()
!atMostOneBranchOrAllEmpty
)
}

Expand Down