com.github.tankist88.carpenter.generator.command.CreateTestMethodCommand Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of carpenter-generator Show documentation
Show all versions of carpenter-generator Show documentation
Carpenter is a framework for unit test generation from runtime data.
package com.github.tankist88.carpenter.generator.command;
import com.github.tankist88.carpenter.core.dto.argument.GeneratedArgument;
import com.github.tankist88.carpenter.core.dto.unit.field.FieldProperties;
import com.github.tankist88.carpenter.core.dto.unit.method.MethodBaseInfo;
import com.github.tankist88.carpenter.core.dto.unit.method.MethodCallInfo;
import com.github.tankist88.carpenter.core.property.GenerationProperties;
import com.github.tankist88.carpenter.core.property.GenerationPropertiesFactory;
import com.github.tankist88.carpenter.generator.dto.PreparedMock;
import com.github.tankist88.carpenter.generator.dto.ProviderNextPartInfo;
import com.github.tankist88.carpenter.generator.dto.SeparatedInners;
import com.github.tankist88.carpenter.generator.dto.SpyMaps;
import com.github.tankist88.carpenter.generator.dto.unit.ClassExtInfo;
import com.github.tankist88.carpenter.generator.dto.unit.imports.ImportInfo;
import com.github.tankist88.carpenter.generator.dto.unit.method.MethodExtInfo;
import com.github.tankist88.carpenter.generator.extension.assertext.AssertExtension;
import com.github.tankist88.object2source.dto.ProviderInfo;
import com.github.tankist88.object2source.dto.ProviderResult;
import java.util.*;
import static com.github.tankist88.carpenter.core.property.AbstractGenerationProperties.COMMON_UTIL_POSTFIX;
import static com.github.tankist88.carpenter.core.property.AbstractGenerationProperties.TAB;
import static com.github.tankist88.carpenter.generator.TestGenerator.*;
import static com.github.tankist88.carpenter.generator.command.CreateMockFieldCommand.CREATE_INST_METHOD;
import static com.github.tankist88.carpenter.generator.util.ConvertUtil.toMethodExtInfo;
import static com.github.tankist88.carpenter.generator.util.GenerateUtil.*;
import static com.github.tankist88.carpenter.generator.util.TypeHelper.*;
import static com.github.tankist88.object2source.util.AssigmentUtil.VAR_NAME_PLACEHOLDER;
import static com.github.tankist88.object2source.util.GenerationUtil.*;
import static java.lang.reflect.Modifier.isAbstract;
import static java.lang.reflect.Modifier.isStatic;
import static java.util.Collections.singletonList;
import static org.apache.commons.lang3.StringUtils.isBlank;
public class CreateTestMethodCommand extends AbstractReturnClassInfoCommand {
private static final int DATA_PROVIDER_MAX_LENGTH_IN_METHODS = 40;
private static final String GOOD_MOCKITO_VERSION = "2.8.9";
public static final String TEST_ANNOTATION = "@Test";
public static final String HASH_CODE_SEPARATOR = "_";
public static final String TEST_METHOD_PREFIX = "test";
public static final String ARRAY_PROVIDER_PREFIX = "getArrProv";
private static final String RESULT_VAR = "result";
private static final String CONTROL_VAR = "control";
private static final String SPY_VAR_NAME = "spyObj";
private StringBuilder builder;
private List assertExtensions;
private MethodCallInfo callInfo;
private Map> providerSignatureMap;
private GenerationProperties props;
private List methods;
private Map> dataProviders;
private Set imports;
private Set mockStaticClassNames;
private Set arrayProviders;
private Set testClassHierarchy;
// serviceFields
private Set testClassFields;
public CreateTestMethodCommand(
MethodCallInfo callInfo,
Map> providerSignatureMap,
Map> dataProviders,
List assertExtensions
) {
this.callInfo = callInfo;
this.providerSignatureMap = providerSignatureMap;
this.props = GenerationPropertiesFactory.loadProps();
this.builder = new StringBuilder();
this.imports = new HashSet<>();
this.dataProviders = dataProviders;
if(assertExtensions != null) {
this.assertExtensions = assertExtensions;
} else {
this.assertExtensions = new ArrayList<>();
}
this.arrayProviders = new HashSet<>();
this.testClassHierarchy = createTestClassHierarchy(callInfo);
this.mockStaticClassNames = new HashSet<>();
this.testClassFields = createServiceFields(callInfo);
}
@Override
public void execute() {
super.execute();
createTestMethod();
}
@Override
public List returnResult() {
List result = new ArrayList<>();
result.addAll(methods);
result.addAll(arrayProviders);
result.addAll(imports);
for(Set set : dataProviders.values()) {
result.addAll(set);
}
return result;
}
private void createTestMethod() {
String testMethodName = (
TEST_METHOD_PREFIX + upFirst(callInfo.getUnitName()) +
HASH_CODE_SEPARATOR + callInfo.getArguments().hashCode() + "()"
).replaceAll("-", "_");
builder.append(TAB + TEST_ANNOTATION + "\n")
.append(TAB + "public void ").append(testMethodName).append(" throws Exception {\n");
List mocks = createMocks();
if (!isCreateMockFields()) {
appendTestInstance();
}
if (props.isFillTestClassInstance()) {
appendInitMethod();
}
appendMocks(mocks);
appendTestCall();
appendMethodCallVerification(mocks);
appendResultCheckAssert();
builder.append(TAB + "}\n");
MethodExtInfo testMethod = new MethodExtInfo(callInfo.getClassName(), testMethodName, builder.toString());
testMethod.getMockStaticClassNames().addAll(mockStaticClassNames);
methods = singletonList(testMethod);
}
private void appendInitMethod() {
GeneratedArgument arg = callInfo.getTargetObj();
if (arg != null && arg.getGenerated() != null && !arg.getGenerated().getEndPoint().isEmpty()) {
builder.append(TAB + TAB).append(createDataProvider(callInfo.getTargetObj())).append(";\n");
}
}
private AssertExtension findAssertExtension(MethodCallInfo callInfo) {
AssertExtension assertExtension = null;
for (AssertExtension ext : assertExtensions) {
if (ext.isTypeSupported(callInfo.getReturnArg())) {
assertExtension = ext;
break;
}
}
return assertExtension;
}
private void appendResultCheckAssert() {
AssertExtension assertExtension = findAssertExtension(callInfo);
if (assertExtension != null) {
builder.append(createVariableAssignment(callInfo.getReturnArg(), CONTROL_VAR));
builder.append(assertExtension.getAssertBlock(RESULT_VAR, CONTROL_VAR));
}
}
private void appendMocks(List mocks) {
for (PreparedMock mock : mocks) {
if (isBlank(mock.getMock())) continue;
builder.append(mock.getMock());
}
}
private void appendMethodCallVerification(List mocks) {
for (PreparedMock mock : mocks) {
if (isBlank(mock.getVerify())) continue;
builder.append(mock.getVerify());
}
}
private String createVariableAssignment(GeneratedArgument generatedArgument, String varName) {
return createVariableAssignment(generatedArgument, varName, false);
}
private String createVariableAssignment(GeneratedArgument generatedArgument, String varName, boolean spy) {
String varType = generatedArgument.getNearestInstantAbleClass();
if(!isPrimitive(varType) && !isWrapper(varType) && !varType.equals(String.class.getName())) {
imports.add(createImportInfo(varType, callInfo.getClassName()));
}
StringBuilder result = new StringBuilder();
result .append(TAB + TAB)
.append(getClassShort(typeOfGenArg(generatedArgument)))
.append(" ").append(varName).append(" = ");
if (spy) {
result.append("spy(").append(createDataProvider(generatedArgument)).append(")");
} else {
result.append(createDataProvider(generatedArgument));
}
result.append(";\n");
return result.toString();
}
private void appendTestCall() {
int i = 0;
StringBuilder argBuilder = new StringBuilder();
StringBuilder providerBuilder = new StringBuilder();
Iterator iterator = callInfo.getArguments().iterator();
while (iterator.hasNext()) {
String argName = "_arg" + i;
providerBuilder.append(createVariableAssignment(iterator.next(), argName));
argBuilder.append(argName);
if(iterator.hasNext()) argBuilder.append(", ");
i++;
}
builder.append(providerBuilder.toString());
builder.append(TAB + TAB);
if (findAssertExtension(callInfo) != null) {
String varType = callInfo.getReturnArg().getNearestInstantAbleClass();
if(!isPrimitive(varType) && !isWrapper(varType) && !varType.equals(String.class.getName())) {
imports.add(createImportInfo(varType, callInfo.getClassName()));
}
builder.append(getLastClassShort(typeOfGenArg(callInfo.getReturnArg()))).append(" " + RESULT_VAR + " = ");
}
if(isStatic(callInfo.getMethodModifiers())) {
builder.append(getClassShort(callInfo.getClassName())).append(".");
} else {
builder.append(TEST_INST_VAR_NAME + ".");
}
builder.append(callInfo.getUnitName()).append("(").append(argBuilder.toString()).append(");\n");
}
private List createMocks() {
Set methodMocks = new HashSet<>();
List fieldMocks = new ArrayList<>();
if (!isStatic(callInfo.getMethodModifiers()) || isUsePowermock()) {
SeparatedInners separatedInners = separateInners(callInfo.getInnerMethods());
SpyMaps spyMaps = createSpyMap(separatedInners);
Set fieldProperties;
if (isCreateMockFields()) {
fieldProperties = testClassFields;
} else {
Set allMethods = new HashSet<>(separatedInners.getSingleInners());
for (Set multiInner : separatedInners.getMultipleInners()) {
allMethods.addAll(multiInner);
}
fieldProperties = filterFieldPropBySpyMaps(createServiceFields(allMethods, testClassFields), spyMaps);
if (!isStatic(callInfo.getMethodModifiers())) {
fieldMocks.addAll(createMockInstances(filterFieldPropByServiceClasses(fieldProperties)));
}
fieldMocks.addAll(createMockStatic(fieldProperties));
}
for (MethodCallInfo inner : separatedInners.getSingleInners()) {
PreparedMock mock = createSingleMock(inner, fieldProperties, spyMaps);
if (mock != null) methodMocks.add(mock);
}
for (Set multiInner : separatedInners.getMultipleInners()) {
PreparedMock mock = createMultipleMock(multiInner, fieldProperties, spyMaps);
if (mock != null) methodMocks.add(mock);
}
}
List methodList = new ArrayList<>(methodMocks);
Collections.sort(methodList, new Comparator() {
@Override
public int compare(PreparedMock o1, PreparedMock o2) {
return o1.getMock().compareTo(o2.getMock());
}
});
List resultList = new ArrayList<>();
resultList.addAll(fieldMocks);
resultList.addAll(methodList);
return resultList;
}
private void appendTestInstance() {
if (isStatic(callInfo.getMethodModifiers())) return;
String clearedClassName = getClearedClassName(callInfo.getNearestInstantAbleClass());
imports.add(createImportInfo(clearedClassName, callInfo.getClassName()));
builder .append(TAB + TAB)
.append(getClassShort(clearedClassName))
.append(" ")
.append(TEST_INST_VAR_NAME)
.append(" = spy(");
if (isAbstract(callInfo.getClassModifiers())) {
builder.append(getClassShort(clearedClassName)).append(".class");
} else if (!callInfo.isClassHasZeroArgConstructor()) {
String createInstMethod = props.getDataProviderClassPattern() + COMMON_UTIL_POSTFIX + "." + CREATE_INST_METHOD;
imports.add(createImportInfo(createInstMethod, callInfo.getClassName(), true));
builder.append("createInstance(").append(getClassShort(clearedClassName)).append(".class)");
} else {
builder.append("new ").append(getClassShort(clearedClassName)).append("()");
}
builder.append(");\n");
}
private Set createMockStatic(Set serviceClasses) {
Set result = new HashSet<>();
for (FieldProperties f : serviceClasses) {
boolean anonymousClass = getLastClassShort(f.getClassName()).matches("\\d+");
if (!isUsePowermock() || !isStatic(f.getModifiers()) || anonymousClass) continue;
String varType = f.getClassName();
if(!isPrimitive(varType) && !isWrapper(varType) && !varType.equals(String.class.getName())) {
imports.add(createImportInfo(varType, callInfo.getClassName()));
}
mockStaticClassNames.add(getClassShort(f.getClassName()));
String mock = TAB + TAB + "PowerMockito.mockStatic(" + getClassShort(f.getClassName()) + ".class);\n";
result.add(new PreparedMock(mock, null));
}
return result;
}
private Set createMockInstances(Set serviceClasses) {
Set result = new HashSet<>();
for (FieldProperties f : serviceClasses) {
boolean testClass = f.getClassName().equals(callInfo.getClassName());
boolean anonymousClass = getLastClassShort(f.getClassName()).matches("\\d+");
if (testClass || anonymousClass) continue;
String varType = f.getClassName();
if(!isPrimitive(varType) && !isWrapper(varType) && !varType.equals(String.class.getName())) {
imports.add(createImportInfo(varType, callInfo.getClassName()));
}
String depInjectMethod = props.getDataProviderClassPattern() + COMMON_UTIL_POSTFIX + ".notPublicAssignment";
imports.add(createImportInfo(depInjectMethod, callInfo.getClassName(), true));
String mock =
TAB + TAB + getClassShort(f.getClassName()) + " " + f.getUnitName() +
" = mock(" + getClassShort(f.getClassName()) + ".class);\n";
String assign =
TAB + TAB + "notPublicAssignment(" + TEST_INST_VAR_NAME + ", \"" + f.getUnitName() +
"\", " + f.getUnitName() + ");\n";
result.add(new PreparedMock(mock + assign, null));
}
return result;
}
private SpyMaps createSpyMap(SeparatedInners separatedInners) {
SpyMaps result = new SpyMaps();
List allMethods = new ArrayList<>(separatedInners.getSingleInners());
for (Set multiInner : separatedInners.getMultipleInners()) {
allMethods.addAll(multiInner);
}
sortMethodCallInfos(allMethods);
int varCounter = 0;
for (MethodCallInfo inner : allMethods) {
for (MethodCallInfo current : allMethods) {
if (inner.getReturnArg() == null || inner.getReturnArg().getGenerated() == null) continue;
String returnType = inner.getReturnArg().getClassName();
if (
inner.getReturnArg().getClassHashCode() == current.getClassHashCode() &&
(inner.getReturnArg().getClassName().equals(current.getClassName()) ||
current.getClassHierarchy().contains(returnType) ||
current.getInterfacesHierarchy().contains(returnType))
) {
result.getReturnSpyMap().put(inner, SPY_VAR_NAME + varCounter);
result.getTargetSpyMap().put(current, SPY_VAR_NAME + varCounter);
}
}
varCounter++;
}
return result;
}
private Set filterFieldPropByServiceClasses(Set fieldProperties) {
Set result = new HashSet<>();
for (FieldProperties f : fieldProperties) {
List typeHierarchy = new ArrayList<>();
typeHierarchy.addAll(f.getClassHierarchy());
typeHierarchy.addAll(f.getInterfacesHierarchy());
boolean contains = false;
for (FieldProperties s : testClassFields) {
if (typeHierarchy.contains(s.getClassName())) {
contains = true;
break;
}
}
if (contains) result.add(f);
}
return result;
}
private Set filterFieldPropBySpyMaps(Set fieldProperties, SpyMaps spyMaps) {
Set result = new HashSet<>();
Set filteredByServices = filterFieldPropByServiceClasses(fieldProperties);
for (FieldProperties f : fieldProperties) {
if (filteredByServices.contains(f) || isStatic(f.getModifiers())) {
result.add(f);
} else {
boolean contains = false;
for (MethodCallInfo m : spyMaps.getTargetSpyMap().keySet()) {
if (m.getClassName().equals(f.getClassName()) && m.getUnitName().startsWith(f.getUnitName())) {
contains = true;
break;
}
}
if (contains) result.add(f);
}
}
return result;
}
private String createArrayProvider(Set innerSet) {
MethodCallInfo innerFirst = innerSet.iterator().next();
String retType = innerFirst.getReturnArg().getClassName();
List methodCallInfoList = new ArrayList<>(innerSet);
sortMethodCallInfos(methodCallInfoList);
StringBuilder bodyBuilder = new StringBuilder();
Iterator methodCallInfoIterator = methodCallInfoList.iterator();
while(methodCallInfoIterator.hasNext()) {
MethodCallInfo m = methodCallInfoIterator.next();
bodyBuilder.append(TAB + TAB + TAB).append(createDataProvider(m.getReturnArg()));
if(methodCallInfoIterator.hasNext()) bodyBuilder.append(",");
bodyBuilder.append("\n");
}
String hashCodeStr = String.valueOf(bodyBuilder.toString().hashCode()).replace("-", "_");
String unitName = ARRAY_PROVIDER_PREFIX + getClassShort(retType) + "_" + hashCodeStr + "()";
String arrayProvider =
TAB + "private " + getClassShort(retType) + "[] " + unitName + " throws Exception {\n" +
TAB + TAB + getClassShort(retType) + "[] values = {\n" + bodyBuilder.toString() +
TAB + TAB + "};\n" + TAB + TAB + "return values;\n" + TAB + "}\n";
arrayProviders.add(new MethodExtInfo(callInfo.getClassName(), unitName, arrayProvider));
return unitName;
}
private String getMockVarName(MethodCallInfo inner, Set serviceClasses, SpyMaps spyMaps) {
if (spyMaps.getTargetSpyMap().containsKey(inner)) return spyMaps.getTargetSpyMap().get(inner);
boolean testClass = inner.getClassName().equals(callInfo.getClassName());
if (testClass) {
return TEST_INST_VAR_NAME;
} else {
return createMockVarName(inner, serviceClasses);
}
}
private PreparedMock createMultipleMock(Set innerSet, Set serviceClasses, SpyMaps spyMaps) {
MethodCallInfo innerFirst = innerSet.iterator().next();
if (skipMock(innerFirst, callInfo, serviceClasses, testClassHierarchy, spyMaps) || forwardMock(innerFirst, callInfo, testClassHierarchy)) return null;
// TODO Implement using spyMaps.getReturnSpyMap() for spy() return values in array provider
String retType = innerFirst.getReturnArg().getClassName();
if (!isPrimitive(retType) && !isWrapper(retType) && !retType.equals(String.class.getName())) {
imports.add(createImportInfo(retType, callInfo.getClassName()));
}
String retShortType = getClassShort(retType);
String arrVarName = "values" + retShortType;
StringBuilder mockBuilder = new StringBuilder();
mockBuilder
.append(createDoExpression(innerFirst, "", true))
.append("(new Answer() {\n" + TAB + "\n")
.append(TAB + TAB + TAB + "private int count = 0;\n" + TAB + "\n")
.append(TAB + TAB + TAB + "private ")
.append(retShortType).append("[] ").append(arrVarName).append(" = ").append(createArrayProvider(innerSet)).append(";\n")
.append(TAB + TAB + TAB + "@Override\n")
.append(TAB + TAB + TAB + "public Object answer(InvocationOnMock invocationOnMock) throws Throwable {\n")
.append(TAB + TAB + TAB + TAB).append(retShortType).append(" result = ").append(arrVarName).append("[count];\n")
.append(TAB + TAB + TAB + TAB + "if (count + 1 < ").append(arrVarName).append(".length)\n")
.append(TAB + TAB + TAB + TAB + TAB + "count++;\n")
.append(TAB + TAB + TAB + TAB + "return result;\n")
.append(TAB + TAB + TAB + "}\n")
.append(TAB + TAB + "}).when(");
mockBuilder.append(createWhen(innerFirst, serviceClasses, spyMaps));
String varName = getMockVarName(innerFirst, serviceClasses, spyMaps);
return new PreparedMock(mockBuilder.toString(), getVerificationBlock(innerFirst, varName, serviceClasses));
}
private PreparedMock createSingleMock(MethodCallInfo inner, Set serviceClasses, SpyMaps spyMaps) {
if (skipMock(inner, callInfo, serviceClasses, testClassHierarchy, spyMaps) || forwardMock(inner, callInfo, testClassHierarchy)) return null;
boolean voidMethod = inner.isVoidMethod();
StringBuilder mockBuilder = new StringBuilder();
if (voidMethod) {
mockBuilder.append(createDoExpression(inner, "", false));
} else {
String dpVar;
if (spyMaps.getReturnSpyMap().containsKey(inner)) {
dpVar = spyMaps.getReturnSpyMap().get(inner);
mockBuilder.append(createVariableAssignment(inner.getReturnArg(), dpVar, true));
} else {
dpVar = createDataProvider(inner.getReturnArg());
}
mockBuilder.append(createDoExpression(inner, dpVar, false));
}
mockBuilder.append(createWhen(inner, serviceClasses, spyMaps));
String varName = getMockVarName(inner, serviceClasses, spyMaps);
return new PreparedMock(mockBuilder.toString(), getVerificationBlock(inner, varName, serviceClasses));
}
private String createWhen(MethodCallInfo inner, Set serviceClasses, SpyMaps spyMaps) {
StringBuilder mockBuilder = new StringBuilder();
if (isUsePowermock() && isStatic(inner.getMethodModifiers())) {
mockBuilder
.append(getClassShort(inner.getClassName())).append(".class, ")
.append("\"").append(inner.getUnitName()).append("\"");
if (inner.getArguments().size() > 0) {
mockBuilder.append(", ");
appendMockArguments(mockBuilder, inner, imports);
}
mockBuilder.append(");\n");
} else {
String varName = getMockVarName(inner, serviceClasses, spyMaps);
mockBuilder.append(varName).append(").").append(inner.getUnitName()).append("(");
appendMockArguments(mockBuilder, inner, imports);
mockBuilder.append(");\n");
}
return mockBuilder.toString();
}
private String createDoExpression(MethodCallInfo inner, String returnExpression, boolean multiple) {
StringBuilder doBuilder = new StringBuilder();
if (isUsePowermock() && isStatic(inner.getMethodModifiers())) {
doBuilder.append(TAB + TAB + "PowerMockito.");
} else {
doBuilder.append(TAB + TAB);
}
if (multiple) {
doBuilder.append("doAnswer");
} else if (isBlank(returnExpression)) {
doBuilder.append("doNothing().when(");
} else {
doBuilder.append("doReturn(").append(returnExpression).append(").when(");
}
return doBuilder.toString();
}
private String getVerificationBlock(MethodCallInfo inner, String varName, Set serviceClasses) {
if (determineVarName(inner, serviceClasses) == null || isStatic(inner.getMethodModifiers())) return null;
StringBuilder verifyBuilder = new StringBuilder();
verifyBuilder.append(TAB + TAB + "verify(");
verifyBuilder.append(varName).append(", atLeastOnce()).").append(inner.getUnitName());
verifyBuilder.append("(");
appendMockArguments(verifyBuilder, inner, imports);
verifyBuilder.append(");\n");
return verifyBuilder.toString();
}
private void appendMockArguments(StringBuilder sb, MethodCallInfo inner, Set imports) {
Iterator iterator = inner.getArguments().iterator();
while (iterator.hasNext()) {
GeneratedArgument arg = iterator.next();
if (arg.getGenerated() != null && arg.getGenericString() != null && arg.getInterfacesHierarchy().contains("java.util.List")) {
sb.append("ArgumentMatchers.<").append(getClassShort(arg.getGenericString())).append(">anyList()");
if(!isPrimitive(arg.getGenericString()) && !isWrapper(arg.getGenericString()) && !arg.getGenericString().equals(String.class.getName())) {
imports.add(createImportInfo(arg.getGenericString(), callInfo.getClassName()));
}
} else if (arg.getGenerated() != null && arg.getGenericString() != null && arg.getInterfacesHierarchy().contains("java.util.Set")) {
sb.append("ArgumentMatchers.<").append(getClassShort(arg.getGenericString())).append(">anySet()");
if(!isPrimitive(arg.getGenericString()) && !isWrapper(arg.getGenericString()) && !arg.getGenericString().equals(String.class.getName())) {
imports.add(createImportInfo(arg.getGenericString(), callInfo.getClassName()));
}
} else if (arg.getGenerated() == null && props.getTargetMockitoVersion().equals(GOOD_MOCKITO_VERSION)) {
sb.append("null");
} else {
String clearedType = getClearedClassName(arg.getNearestInstantAbleClass());
sb.append("nullable(").append(getClassShort(clearedType)).append(".class").append(")");
if(!isPrimitive(clearedType) && !isWrapper(clearedType) && !clearedType.equals(String.class.getName())) {
imports.add(createImportInfo(clearedType, callInfo.getClassName()));
}
}
if (iterator.hasNext()) sb.append(", ");
}
}
private String createDataProvider(GeneratedArgument arg) {
String result;
ProviderResult providerResult = arg.getGenerated();
if (providerResult != null) {
MethodBaseInfo dp = getProviderNameAndUpdateState(providerResult);
result = dp.getUnitName();
if(!isPrimitive(dp.getClassName()) && !isWrapper(dp.getClassName()) && !dp.getClassName().equals(String.class.getName())) {
String importClass = dp.getClassName()+ "." + dp.getUnitName().substring(0, dp.getUnitName().indexOf("("));
imports.add(createImportInfo(importClass, callInfo.getClassName(), true));
}
} else {
String dpType = arg.getNearestInstantAbleClass();
result = "(" + getClassShort(convertPrimitiveToWrapper(dpType)) + ") null";
if(!isPrimitive(dpType) && !isWrapper(dpType) && !dpType.equals(String.class.getName())) {
imports.add(createImportInfo(dpType, callInfo.getClassName()));
}
}
return result;
}
private String createInnerKey(MethodCallInfo inner) {
StringBuilder argTypes = new StringBuilder();
Iterator iterator = inner.getArguments().iterator();
while (iterator.hasNext()) {
argTypes.append(iterator.next().getNearestInstantAbleClass());
if (iterator.hasNext()) argTypes.append(", ");
}
return inner.getClassName() + "-" +
inner.getUnitName() + "-" +
inner.getMethodModifiers() + "-" +
argTypes.toString();
}
private Map> createSetOfSetInners(Set inners) {
Map> innerMap = new HashMap<>();
for(MethodCallInfo inner : inners) {
if (skipMock(inner, callInfo, testClassFields, testClassHierarchy, null)) continue;
for(MethodCallInfo current : inners) {
if (createInnerKey(current).equals(createInnerKey(inner))) {
Set innerSet = innerMap.get(createInnerKey(current));
if (innerSet == null) {
innerSet = new HashSet<>();
innerMap.put(createInnerKey(current), innerSet);
}
innerSet.add(current);
}
}
if (forwardMock(inner, callInfo, testClassHierarchy)) {
Map> recMap = createSetOfSetInners(inner.getInnerMethods());
for (Map.Entry> entry : recMap.entrySet()) {
Set innerSet = innerMap.get(entry.getKey());
if (innerSet != null) {
innerSet.addAll(entry.getValue());
} else {
innerMap.put(entry.getKey(), entry.getValue());
}
}
}
}
return innerMap;
}
private SeparatedInners separateInners(Set inners) {
SeparatedInners result = new SeparatedInners();
for (Set set : createSetOfSetInners(inners).values()) {
if (set.size() > 1) {
boolean allReturnNulls = true;
for (MethodCallInfo m : set) {
if (m.getReturnArg().getGenerated() != null) {
allReturnNulls = false;
break;
}
}
boolean allReturnEquals = true;
ProviderResult prevProvider = set.iterator().next().getReturnArg().getGenerated();
for (MethodCallInfo m : set) {
if (m.getReturnArg().getGenerated() != null && !m.getReturnArg().getGenerated().equals(prevProvider)) {
allReturnEquals = false;
break;
} else {
prevProvider = m.getReturnArg().getGenerated();
}
}
MethodCallInfo mc = set.iterator().next();
if (mc.isVoidMethod() || allReturnNulls || allReturnEquals) {
result.getSingleInners().add(mc);
} else {
result.getMultipleInners().add(set);
}
} else {
result.getSingleInners().add(set.iterator().next());
}
}
return result;
}
private MethodBaseInfo getProviderNameAndUpdateState(ProviderResult providerResult) {
String methodName = providerResult.getEndPoint().getMethodName().replace(VAR_NAME_PLACEHOLDER, TEST_INST_VAR_NAME);
String existsClassName = getExistsProviderClassName(methodName);
if(existsClassName != null) {
return new MethodBaseInfo(existsClassName, methodName);
} else {
ProviderNextPartInfo dataProviderInfo = getNextProviderClassName();
Set methodsSig = this.providerSignatureMap.get(dataProviderInfo.getClassName());
if (methodsSig == null) {
methodsSig = new HashSet<>();
this.providerSignatureMap.put(dataProviderInfo.getClassName(), methodsSig);
}
for (ProviderInfo provider : providerResult.getProviders()) {
String currProviderName = provider.getMethodName().replace(VAR_NAME_PLACEHOLDER, TEST_INST_VAR_NAME);
if (!methodsSig.contains(currProviderName)) {
dataProviderInfo.getMethods().add(toMethodExtInfo(dataProviderInfo.getClassName(), provider));
methodsSig.add(currProviderName);
}
}
return new MethodBaseInfo(dataProviderInfo.getClassName(), methodName);
}
}
private ProviderNextPartInfo getNextProviderClassName() {
ProviderNextPartInfo result = new ProviderNextPartInfo();
int dataProviderCount = providerSignatureMap.size();
String dataProviderClassName =
this.props.getDataProviderClassPattern() +
String.valueOf(dataProviderCount);
Set dataProviderMethods = this.dataProviders.get(dataProviderClassName);
if(dataProviderMethods == null || dataProviderMethods.size() >= DATA_PROVIDER_MAX_LENGTH_IN_METHODS) {
dataProviderMethods = new HashSet<>();
dataProviderClassName =
this.props.getDataProviderClassPattern() +
String.valueOf(dataProviderCount + 1);
this.dataProviders.put(dataProviderClassName, dataProviderMethods);
}
result.setClassName(dataProviderClassName);
result.setMethods(dataProviderMethods);
return result;
}
private String getExistsProviderClassName(String currentMethodName) {
String methodClass = null;
List>> entryList = new ArrayList<>(providerSignatureMap.entrySet());
Collections.sort(entryList, new Comparator>>() {
@Override
public int compare(Map.Entry> o1, Map.Entry> o2) {
int num1 = extractNumber(o1.getKey());
int num2 = extractNumber(o2.getKey());
return num1 - num2;
}
private int extractNumber(String classname) {
String dpPattern = props.getDataProviderClassPattern();
String num = classname.substring(classname.indexOf(dpPattern) + dpPattern.length());
if (num.equals(COMMON_UTIL_POSTFIX)) {
return Integer.MAX_VALUE;
} else {
return Integer.parseInt(num);
}
}
});
for (Map.Entry> entry : entryList) {
for (String method : entry.getValue()) {
if (method.equals(currentMethodName)) {
methodClass = entry.getKey();
break;
}
}
if (methodClass != null) break;
}
return methodClass;
}
}