Skip to content

Commit

Permalink
Use controllers via MockMvc in Spring integration tests (#2447)
Browse files Browse the repository at this point in the history
* Use controllers via `MockMvc` in concrete execution and update result models

* Make `createGetMockMvcResponseModel` work when there's no `@RequestMapping` on controller class

* Introduce `executableToCall`

* Replace `executableToCall` with `MockMvc.perform` for Spring controllers

* Remove handling of Spring controllers from `SpringUtExecutionInstrumentation`

* Add `utCustomModelConstructorFinder` property to `UtModelConstructor`

* Add `UtSpringMockMvcResultActionsModel` and its `UtCustomModelConstructor`

* Add `UtCustomModel` (i.e. common parent of all framework specific models)

* Properly handle `UtCustomModel`

* Add `origin` to `UtSpringMockMvcResultActionsModel`

* Split `CgMethodTestSet.executableId` into `executableUnderTest` and `executablesToCall`

* Enable `UtMockMvcResultActionsModelConstructor` for subtypes of `ResultActions`

* Add `CgCustomAssertConstructor` to `CgComponents`

* Add custom asserts for `MockMvc.perform()` result

* Remove redundant code

* Handle `modelTagName` for `UtCustomModel`

* Fix compilation after rebase

* Fix JS compilation

* Address comments in #2447
  • Loading branch information
IlyaMuravjov authored Aug 1, 2023
1 parent 65683b0 commit c21a916
Show file tree
Hide file tree
Showing 58 changed files with 1,310 additions and 374 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ abstract class UtExecution(
testMethodName: String? = this.testMethodName,
displayName: String? = this.displayName,
): UtExecution

val executableToCall get() = stateBefore.executableToCall
}

/**
Expand Down Expand Up @@ -287,11 +289,33 @@ class UtFailedExecution(
}
}

/**
* @property executableToCall executable that is called in the test body and whose result is used in asserts as `actual`.
*
* Most often [executableToCall] is just method under test, but it may be changed to different executable if more
* appropriate way of calling specific method is found (for example, Spring controller methods are called via `MockMvc`).
*
* `null` value of [executableToCall] indicates that method under test should be called in the test body.
*/
open class EnvironmentModels(
val thisInstance: UtModel?,
val parameters: List<UtModel>,
val statics: Map<FieldId, UtModel>
val statics: Map<FieldId, UtModel>,
val executableToCall: ExecutableId?,
) {
@Deprecated("Now `executableToCall` also need to be passed to `EnvironmentModels` constructor " +
"(see more details in `EnvironmentModels` class documentation)", level = DeprecationLevel.ERROR)
constructor(
thisInstance: UtModel?,
parameters: List<UtModel>,
statics: Map<FieldId, UtModel>,
) : this(
thisInstance = thisInstance,
parameters = parameters,
statics = statics,
executableToCall = null,
)

override fun toString() = buildString {
append("this=$thisInstance")
appendOptional("parameters", parameters)
Expand All @@ -305,8 +329,9 @@ open class EnvironmentModels(
fun copy(
thisInstance: UtModel? = this.thisInstance,
parameters: List<UtModel> = this.parameters,
statics: Map<FieldId, UtModel> = this.statics
) = EnvironmentModels(thisInstance, parameters, statics)
statics: Map<FieldId, UtModel> = this.statics,
executableToCall: ExecutableId? = this.executableToCall,
) = EnvironmentModels(thisInstance, parameters, statics, executableToCall)
}

/**
Expand All @@ -315,7 +340,8 @@ open class EnvironmentModels(
object MissingState : EnvironmentModels(
thisInstance = null,
parameters = emptyList(),
statics = emptyMap()
statics = emptyMap(),
executableToCall = null,
)

/**
Expand Down Expand Up @@ -550,6 +576,21 @@ data class UtArrayModel(
override fun hashCode(): Int = id
}

/**
* Wrapper of [origin] model, that can be handled in a different
* way in some situations (e.g. during value construction).
*/
sealed class UtModelWithCompositeOrigin(
id: Int?,
classId: ClassId,
modelName: String = id.toString(),
open val origin: UtCompositeModel?,
) : UtReferenceModel(
id = id,
classId = classId,
modelName = modelName
)

/**
* Model for complex objects with assemble instructions.
*
Expand All @@ -564,8 +605,8 @@ data class UtAssembleModel private constructor(
override val modelName: String,
val instantiationCall: UtStatementCallModel,
val modificationsChain: List<UtStatementModel>,
val origin: UtCompositeModel?
) : UtReferenceModel(id, classId, modelName) {
override val origin: UtCompositeModel?
) : UtModelWithCompositeOrigin(id, classId, modelName, origin) {

/**
* Creates a new [UtAssembleModel].
Expand Down Expand Up @@ -703,7 +744,17 @@ class UtLambdaModel(
}
}

object UtSpringContextModel : UtReferenceModel(
/**
* Common parent of all framework-specific models (e.g. Spring-specific models)
*/
abstract class UtCustomModel(
id: Int?,
classId: ClassId,
modelName: String = id.toString(),
override val origin: UtCompositeModel? = null,
) : UtModelWithCompositeOrigin(id, classId, modelName, origin)

object UtSpringContextModel : UtCustomModel(
id = null,
classId = SpringModelUtils.applicationContextClassId,
modelName = "applicationContext"
Expand All @@ -721,6 +772,23 @@ data class SpringRepositoryId(
val entityClassId: ClassId,
)

class UtSpringMockMvcResultActionsModel(
id: Int?,
origin: UtCompositeModel?,
val status: Int,
val errorMessage: String?,
val contentAsString: String,
val viewName: String?,
// model for mvcResult.modelAndView?.model
val model: UtModel?
// TODO add headers and other data
) : UtCustomModel(
origin = origin,
classId = SpringModelUtils.resultActionsClassId,
id = id,
modelName = "mockMvcResultActions@$id"
)

/**
* Model for a step to obtain [UtAssembleModel].
*/
Expand Down
Loading

0 comments on commit c21a916

Please sign in to comment.