Skip to content
Prev Previous commit
Next Next commit
Apply fixes under review
  • Loading branch information
EgorkaKulikov committed Mar 9, 2023
commit fb0d0813de57aa221cbb05a8442feb62c57968a4
Original file line number Diff line number Diff line change
Expand Up @@ -1157,7 +1157,13 @@ class WildcardTypeParameter : TypeParameters(emptyList())
open class StandardApplicationContext(
val mockFrameworkInstalled: Boolean = true,
val staticsMockingIsConfigured: Boolean = true,
)
) {
init {
if (!mockFrameworkInstalled) {
require(!staticsMockingIsConfigured) { "Static mocking cannot be used without mock framework" }
}
}
}

/**
* Data we get from Spring application context
Expand Down
53 changes: 31 additions & 22 deletions utbot-framework/src/main/kotlin/org/utbot/engine/Mocks.kt
Original file line number Diff line number Diff line change
Expand Up @@ -132,21 +132,30 @@ data class UtStaticMethodMockInfo(
/**
* A wrapper for [ObjectValue] to store additional onfo.
*/
sealed class MockedObjectInfo(val value: ObjectValue?)
sealed class MockedObjectInfo {
abstract val value: ObjectValue?
}

object NoMock: MockedObjectInfo(value = null)
object NoMock: MockedObjectInfo() {
override val value: ObjectValue? = null
}

/**
* Represents a mock that occurs when mock strategy allows it
* or when an object type is in a set that requires force mocking.
*/
class ExpectedMock(value: ObjectValue): MockedObjectInfo(value)
class ExpectedMock(objectValue: ObjectValue): MockedObjectInfo() {
override val value: ObjectValue = objectValue
}

/**
* Represents a mock that occurs when it is not recommended
* E.g. mock strategy recommends do not mock
* E.g. mock framework is not installed or
* mock startegy is DO_NOT_MOCK and class is not in mockAlways set.
*/
class UnexpectedMock(value: ObjectValue): MockedObjectInfo(value)
class UnexpectedMock(objectValue: ObjectValue): MockedObjectInfo() {
override val value: ObjectValue = objectValue
}

/**
* Service to mock things. Knows mock strategy, class under test and class hierarchy.
Expand All @@ -166,24 +175,24 @@ class Mocker(
* an information if this mock is expected or not.
*/
fun construct(value: ObjectValue?, mockInfo: UtMockInfo): MockedObjectInfo {
return value
?.let {
val mockingIsPossible = when (mockInfo) {
is UtFieldMockInfo,
is UtObjectMockInfo -> applicationContext.mockFrameworkInstalled
is UtNewInstanceMockInfo,
is UtStaticMethodMockInfo,
is UtStaticObjectMockInfo -> applicationContext.staticsMockingIsConfigured
}
val mockingIsForcedAndPossible = mockAlways(it.type) && mockingIsPossible
if (value == null) {
return NoMock
}

if (mocksAreDesired || mockingIsForcedAndPossible) {
ExpectedMock(it)
} else {
UnexpectedMock(it)
}
}
?: NoMock
val mockingIsPossible = when (mockInfo) {
is UtFieldMockInfo,
is UtObjectMockInfo -> applicationContext.mockFrameworkInstalled
is UtNewInstanceMockInfo,
is UtStaticMethodMockInfo,
is UtStaticObjectMockInfo -> applicationContext.staticsMockingIsConfigured
}
val mockingIsForcedAndPossible = mockAlways(value.type) && mockingIsPossible

return if (mocksAreDesired || mockingIsForcedAndPossible) {
ExpectedMock(value)
} else {
UnexpectedMock(value)
}
}

/**
Expand Down
22 changes: 16 additions & 6 deletions utbot-framework/src/main/kotlin/org/utbot/engine/Traverser.kt
Original file line number Diff line number Diff line change
Expand Up @@ -1384,6 +1384,9 @@ class Traverser(

val mockedObject = mockedObjectInfo.value
if (mockedObjectInfo is UnexpectedMock) {
// if mock occurs, but it is unexpected due to some reasons
// (e.g. we do not have mock framework installed),
// we can only generate a test that uses null value for mocked object
queuedSymbolicStateUpdates += nullEqualityConstraint.asHardConstraint()
}

Expand Down Expand Up @@ -1474,10 +1477,17 @@ class Traverser(
val mockInfo = mockInfoGenerator.generate(addr)
val mockedObjectInfo = mocker.forceMock(type, mockInfoGenerator.generate(addr))

val mockedObject = mockedObjectInfo.value ?: error("Mocked value cannot be null after force mock")
if (mockedObjectInfo is UnexpectedMock) {
queuedSymbolicStateUpdates += nullEqualityConstraint.asHardConstraint()
return mockedObject
val mockedObject: ObjectValue = when (mockedObjectInfo) {
is NoMock -> error("Value must be mocked after the fore mock")
is ExpectedMock -> mockedObjectInfo.value
is UnexpectedMock -> {
// if mock occurs, but it is unexpected due to some reasons
// (e.g. we do not have mock framework installed),
// we can only generate a test that uses null value for mocked object
queuedSymbolicStateUpdates += nullEqualityConstraint.asHardConstraint()

mockedObjectInfo.value
}
}

queuedSymbolicStateUpdates += MemoryUpdate(mockInfos = persistentListOf(MockInfoEnriched(mockInfo)))
Expand Down Expand Up @@ -2680,7 +2690,7 @@ class Traverser(
} ?: findMethodInvocationTargets(types, methodSubSignature)

return methodInvocationTargets
.mapNotNull { (method, implementationClass, possibleTypes) ->
.map { (method, implementationClass, possibleTypes) ->
val typeStorage = typeResolver.constructTypeStorage(implementationClass, possibleTypes)
val mockInfo = memory.mockInfoByAddr(instance.addr)
val mockedObjectInfo = mockInfo?.let {
Expand Down Expand Up @@ -2710,7 +2720,7 @@ class Traverser(
InvocationTarget(wrapperOrInstance, method, constraints)
}
is ExpectedMock -> {
val mockedObject = mockedObjectInfo.value!!
val mockedObject = mockedObjectInfo.value
val typeConstraint = typeRegistry.typeConstraint(mockedObject.addr, mockedObject.typeStorage)
val constraints = setOf(typeConstraint.isOrNullConstraint())

Expand Down