Skip to content

Commit 9475bbd

Browse files
authored
Do not miss non-injected fields in Spring unit test generation #2386 (#2398)
1 parent 2e91edf commit 9475bbd

File tree

2 files changed

+37
-24
lines changed

2 files changed

+37
-24
lines changed

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgSpringVariableConstructor.kt

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,21 @@ class CgSpringVariableConstructor(context: CgContext) : CgVariableConstructor(co
2323
override fun getOrCreateVariable(model: UtModel, name: String?): CgValue {
2424
val alreadyCreatedInjectMocks = findCgValueByModel(model, annotatedModelVariables[injectMocksClassId])
2525
if (alreadyCreatedInjectMocks != null) {
26-
val fields: Collection<UtModel> = when (model) {
27-
is UtCompositeModel -> model.fields.values
28-
is UtAssembleModel -> model.origin?.fields?.values ?: emptyList()
29-
else -> emptyList()
26+
val modelFields = when (model) {
27+
is UtCompositeModel -> model.fields
28+
is UtAssembleModel -> model.origin?.fields
29+
else -> null
3030
}
3131

32-
fields.forEach { getOrCreateVariable(it) }
32+
modelFields?.forEach{ (fieldId, fieldModel) ->
33+
val variableForField = getOrCreateVariable(fieldModel)
34+
35+
// If field model is a mock, it is set in the connected with instance under test automatically via @InjectMocks;
36+
// Otherwise we need to set this field manually.
37+
if(!fieldModel.isMockModel()) {
38+
setFieldValue(alreadyCreatedInjectMocks, fieldId, variableForField)
39+
}
40+
}
3341

3442
return alreadyCreatedInjectMocks
3543
}

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgVariableConstructor.kt

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import org.utbot.framework.codegen.util.nullLiteral
2222
import org.utbot.framework.codegen.util.resolve
2323
import org.utbot.framework.plugin.api.BuiltinClassId
2424
import org.utbot.framework.plugin.api.ClassId
25+
import org.utbot.framework.plugin.api.FieldId
2526
import org.utbot.framework.plugin.api.CodegenLanguage
2627
import org.utbot.framework.plugin.api.ConstructorId
2728
import org.utbot.framework.plugin.api.MethodId
@@ -169,30 +170,34 @@ open class CgVariableConstructor(val context: CgContext) :
169170
}
170171

171172
for ((fieldId, fieldModel) in model.fields) {
172-
val field = fieldId.jField
173173
val variableForField = getOrCreateVariable(fieldModel)
174-
val fieldFromVariableSpecifiedType = obj.type.findFieldByIdOrNull(fieldId)
175-
176-
// we cannot set field directly if variable declared type does not have such field
177-
// or we cannot directly create variable for field with the specified type (it is private, for example)
178-
// Example:
179-
// Object heapByteBuffer = createInstance("java.nio.HeapByteBuffer");
180-
// branchRegisterRequest.byteBuffer = heapByteBuffer;
181-
// byteBuffer is field of type ByteBuffer and upper line is incorrect
182-
val canFieldBeDirectlySetByVariableAndFieldTypeRestrictions =
183-
fieldFromVariableSpecifiedType != null && fieldFromVariableSpecifiedType.type.id == variableForField.type
184-
if (canFieldBeDirectlySetByVariableAndFieldTypeRestrictions && fieldId.canBeSetFrom(context, obj.type)) {
185-
// TODO: check if it is correct to use declaringClass of a field here
186-
val fieldAccess = if (field.isStatic) CgStaticFieldAccess(fieldId) else CgFieldAccess(obj, fieldId)
187-
fieldAccess `=` variableForField
188-
} else {
189-
// composite models must not have info about static fields, hence only non-static fields are set here
190-
+utilsClassId[setField](obj, fieldId.declaringClass.name, fieldId.name, variableForField)
191-
}
174+
setFieldValue(obj, fieldId, variableForField)
192175
}
193176
return obj
194177
}
195178

179+
protected fun setFieldValue(obj: CgValue, fieldId: FieldId, variableForField: CgValue){
180+
val field = fieldId.jField
181+
val fieldFromVariableSpecifiedType = obj.type.findFieldByIdOrNull(fieldId)
182+
183+
// we cannot set field directly if variable declared type does not have such field
184+
// or we cannot directly create variable for field with the specified type (it is private, for example)
185+
// Example:
186+
// Object heapByteBuffer = createInstance("java.nio.HeapByteBuffer");
187+
// branchRegisterRequest.byteBuffer = heapByteBuffer;
188+
// byteBuffer is field of type ByteBuffer and upper line is incorrect
189+
val canFieldBeDirectlySetByVariableAndFieldTypeRestrictions =
190+
fieldFromVariableSpecifiedType != null && fieldFromVariableSpecifiedType.type.id == variableForField.type
191+
if (canFieldBeDirectlySetByVariableAndFieldTypeRestrictions && fieldId.canBeSetFrom(context, obj.type)) {
192+
// TODO: check if it is correct to use declaringClass of a field here
193+
val fieldAccess = if (field.isStatic) CgStaticFieldAccess(fieldId) else CgFieldAccess(obj, fieldId)
194+
fieldAccess `=` variableForField
195+
} else {
196+
// composite models must not have info about static fields, hence only non-static fields are set here
197+
+utilsClassId[setField](obj, fieldId.declaringClass.name, fieldId.name, variableForField)
198+
}
199+
}
200+
196201
private fun constructAssemble(model: UtAssembleModel, baseName: String?): CgValue {
197202
instantiateAssembleModel(model, baseName)
198203
return constructAssembleForVariable(model)

0 commit comments

Comments
 (0)