use of org.evosuite.testcase.fm.MethodDescriptor in project evosuite by EvoSuite.
the class TestCodeVisitor method visitFunctionalMockStatement.
@Override
public void visitFunctionalMockStatement(FunctionalMockStatement st) {
VariableReference retval = st.getReturnValue();
// If it is not used, then minimizer will delete the statement anyway
// boolean unused = test!=null && !test.hasReferences(retval);
// if(unused){
// //no point whatsoever in creating a mock that is never used
// return;
// }
String result = "";
// by construction, we should avoid cases like:
// Object obj = mock(Foo.class);
// as it leads to problems when setting up "when(...)", and anyway it would make no sense
Class<?> rawClass = new GenericClass(retval.getType()).getRawClass();
Class<?> targetClass = st.getTargetClass();
assert rawClass.getName().equals(targetClass.getName()) : "Mismatch between variable raw type " + rawClass + " and mocked " + targetClass;
String rawClassName = getClassName(rawClass);
// Foo foo = mock(Foo.class);
String variableType = getClassName(retval);
result += variableType + " " + getVariableName(retval);
result += " = ";
if (!variableType.equals(rawClassName)) {
// this can happen in case of generics, eg
// Foo<String> foo = (Foo<String>) mock(Foo.class);
result += "(" + variableType + ") ";
}
/*
Tricky situation. Ideally, we would want to throw assumption error if a non-mocked method
is called, as to avoid false-positives when SUTs evolve.
However, it might well be that a test case is not updated, leaving mocks using the default
"null" return values. This would crash the JUnit check. Activating the ViolatedAssumptionAnswer
during the search would just make things worse, as negatively effecting the search.
So we could just skip it, but this would effect false-positive preventions
*/
if (st.doesNeedToUpdateInputs()) {
try {
st.updateMockedMethods();
} catch (Exception e) {
}
st.fillWithNullRefs();
// result += "mock(" + rawClassName + ".class);" + NEWLINE;
} else {
// result += "mock(" + rawClassName + ".class, new " + ViolatedAssumptionAnswer.class.getSimpleName() + "());" + NEWLINE;
}
if (st instanceof FunctionalMockForAbstractClassStatement) {
result += "mock(" + rawClassName + ".class, CALLS_REAL_METHODS);" + NEWLINE;
} else {
result += "mock(" + rawClassName + ".class, new " + ViolatedAssumptionAnswer.class.getSimpleName() + "());" + NEWLINE;
}
// when(...).thenReturn(...)
for (MethodDescriptor md : st.getMockedMethods()) {
if (!md.shouldBeMocked()) {
continue;
}
List<VariableReference> params = st.getParameters(md.getID());
GenericClass returnType = md.getReturnClass();
// Class<?> returnType = md.getMethod().getReturnType();
String parameter_string;
if (!returnType.isPrimitive()) {
Type[] types = new Type[params.size()];
boolean isOverloaded = false;
for (int i = 0; i < types.length; i++) {
if (types.length > 1 && returnType.isArray()) {
types[i] = Object.class;
isOverloaded = true;
} else {
types[i] = params.get(i).getType();
}
}
// TODO unsure of these parameters
parameter_string = getParameterString(types, params, false, isOverloaded, 0);
} else {
// if return type is a primitive, then things can get complicated due to autoboxing :(
parameter_string = getParameterStringForFMthatReturnPrimitive(returnType.getRawClass(), params);
}
// this does not work when throwing exception as default answer
// result += "when("+getVariableName(retval)+"."+md.getMethodName()+"("+md.getInputParameterMatchers()+"))";
// result += ".thenReturn( ";
// result += parameter_string + " );"+NEWLINE;
// Mockito doReturn() only takes single arguments. So we need to make sure that in the generated
// tests we import MockitoExtension class
// parameter_string = "doReturn(" + parameter_string.replaceAll(", ", ").doReturn(") + ")";
// result += parameter_string+".when("+getVariableName(retval)+")";
result += "doReturn(" + parameter_string + ").when(" + getVariableName(retval) + ")";
result += "." + md.getMethodName() + "(" + md.getInputParameterMatchers() + ");";
result += NEWLINE;
}
testCode += result;
}
Aggregations