package com.citi.sl.tlc.common.extract; import java.io.BufferedWriter; import java.io.IOException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import org.apache.commons.lang3.RandomStringUtils; import com.gemstone.bp.edu.emory.mathcs.backport.java.util.Arrays; import com.google.common.collect.Lists; import com.google.common.collect.Maps; public class TestCaseGenerator { private static final String FILE_SUFFIX_LOWERCASE = ".java"; private static final String FILE_SUFFIX_UPPERCASE = ".JAVA"; public static void main(String[] args) { generateTestCaseFiles( "C:\\Users\\pz\\git\\dev\\xx\\xx\\xx\\src\\main\\java"); } /** * Example1 : * C:\\Users\\pz\\git\\trade\\ * * @param projectAbsolutePath */ public static void generateTestCaseFiles(String projectAbsolutePath) { ListfolderList = getAllSubFolders(Paths.get(projectAbsolutePath)); if (folderList.isEmpty()) { System.out.println("folder not exist or no files."); } folderList.forEach(sourceDir -> { Path sourcePath = Paths.get(sourceDir); String testFolderStr = sourceDir.replace("\\src\\main", "\\src\\test"); Path createdTestFolderPath = createTestCaseFolder(Paths.get(testFolderStr)); createTestCaseFile(sourcePath, createdTestFolderPath); }); } public static List getAllSubFolders(Path path) { List folders = new ArrayList<>(); try { if (path.toFile().isDirectory()) { folders.add(path.toFile().getAbsolutePath()); Files.list(path).forEach(f -> { List subFolders = getAllSubFolders(f); folders.addAll(subFolders); }); } } catch (IOException e) { exitProcess(e); } return folders; } private static Path createTestCaseFolder(Path createTargetPath) { try { if (notExists(createTargetPath)) { return Files.createDirectories(createTargetPath); } } catch (IOException e) { exitProcess(e); } return createTargetPath; } private static void createTestCaseFile(Path sourcePath, Path testFolderPath) { try { Files.list(sourcePath).forEach(sourceFilePath -> { if (sourceFilePath.toFile().isFile() && (sourceFilePath.toString().endsWith(FILE_SUFFIX_UPPERCASE) || sourceFilePath.toString().endsWith(FILE_SUFFIX_LOWERCASE))) { buildTestClass(sourceFilePath, testFolderPath); } }); } catch (IOException e) { exitProcess(e); } } private static void buildTestClass(Path sourceFilePath, Path targetFolder) { String className = sourceFilePath.getFileName().toString().replace(FILE_SUFFIX_LOWERCASE, ""); try { Path newTestFilePath = targetFolder.resolve(className + "Test" + FILE_SUFFIX_LOWERCASE); if (notExists(newTestFilePath)) { String javaPath = convertPathToPackageClass(sourceFilePath); Class> sourceClass = getSourceClass(javaPath); if (isJavaBean(sourceClass)) { newTestFilePath = Files.createFile(newTestFilePath); writeJavaBeanTestClass(sourceClass, newTestFilePath); System.out.println("JavaBean :" + newTestFilePath.toString() + " created."); } else if (isNotAbstract(sourceClass) && isNotInterface(sourceClass)) { newTestFilePath = Files.createFile(newTestFilePath); writeTestClass(sourceClass, newTestFilePath); System.out.println(newTestFilePath.toString() + " created."); } } } catch (IOException e) { exitProcess(e); } } private static void writeTestClass(Class> sourceClass, Path newTestFilePath) { String className = sourceClass.getSimpleName(); Set methodNames = getClassPublicMethods(sourceClass); Map methodMap = getMethodMap(sourceClass); String packageLine = sourceClass.getPackage().toString(); BufferedWriter writer = null; try { writer = Files.newBufferedWriter(newTestFilePath); StringBuilder fileBuilder = new StringBuilder(); fileBuilder.append(packageLine + ";\n"); fileBuilder.append("\n"); String importPackage = "import org.mockito.InjectMocks;\r\n" + "import org.mockito.MockitoAnnotations;\r\n" + "import org.junit.Before;\r\n" + "import org.junit.Test;"; fileBuilder.append(importPackage); fileBuilder.append("\n"); fileBuilder.append("public class " + className + "Test{\n"); fileBuilder.append("\n"); fileBuilder.append("\t"); fileBuilder.append("@InjectMocks\n"); fileBuilder.append("\t"); fileBuilder.append("private " + className + " " + firstCharLowerCase(className) + ";\n"); fileBuilder.append(getInitMethodString()); for (String methodName : methodNames) { fileBuilder.append(generateTestMethod(methodName, methodMap)); } fileBuilder.append("\n\n}"); writer.write(fileBuilder.toString()); } catch (IOException e) { exitProcess(e); } finally { if (null != writer) { try { writer.close(); } catch (IOException e) { exitProcess(e); } } } } private static void writeJavaBeanTestClass(Class> sourceClass, Path newTestFilePath) { String className = sourceClass.getSimpleName(); String packageLine = sourceClass.getPackage().toString(); BufferedWriter writer = null; try { writer = Files.newBufferedWriter(newTestFilePath); StringBuilder fileBuilder = new StringBuilder(); fileBuilder.append(packageLine + ";\n"); fileBuilder.append("\n"); fileBuilder.append(generateJavaBeanTestClass(sourceClass.getPackage().getName(), className)); writer.write(fileBuilder.toString()); } catch (IOException e) { exitProcess(e); } finally { if (null != writer) { try { writer.close(); } catch (IOException e) { exitProcess(e); } } } } private static String generateJavaBeanTestClass(String packageName, String className) { String packageImport = "import java.beans.PropertyDescriptor;\r\n" + "import java.lang.reflect.Field;\r\n" + "import java.lang.reflect.Method;\r\n" + "\r\n" + "import org.junit.Before;\r\n" + "import org.junit.Test;\r\n" + "import org.mockito.InjectMocks;\r\n" + "import org.mockito.MockitoAnnotations;\n"; String classBodyStart = "public class " + className + "Test{\n"; String method = " \r\n" + " @InjectMocks\r\n" + " private " + className + " " + firstCharLowerCase(className) + ";\r\n" + "\r\n" + " @Before\r\n" + " public void initMocks(){\r\n" + " MockitoAnnotations.initMocks(this);\r\n" + " }\r\n" + " @Test\r\n" + " public void testSetGetMethod() {\r\n" + " try {\r\n" + " Class> clazz = Class.forName(\"" + packageName + "." + className + "\");\r\n" + " Object obj = clazz.newInstance();\r\n" + " Field[] fields = clazz.getDeclaredFields();\r\n" + " for (Field f : fields) {\r\n" + " try {\r\n" + " PropertyDescriptor pd = new PropertyDescriptor(f.getName(), clazz);\r\n" + " Method writeMethod = pd.getWriteMethod();\r\n" + " writeMethod.invoke(obj, new Object[] { null });\r\n" + " Method readMethod = pd.getReadMethod();\r\n" + " readMethod.invoke(obj);\r\n" + " } catch (Exception e) {\r\n" + " System.out.println(e);\r\n" + " }\r\n" + " }\r\n" + " } catch (Exception e) {\r\n" + " System.out.println(e);\r\n" + " }\r\n" + "\r\n" + " }"; String classBodyEnd = "}"; StringBuilder builder = new StringBuilder(); builder.append(packageImport); builder.append("\n\n"); builder.append(classBodyStart); builder.append(method); builder.append(classBodyEnd); return builder.toString(); } private static boolean isJavaBean(Class> sourceClass) { String fullPackage = sourceClass.getPackage().getName().toLowerCase(); return (fullPackage.endsWith(".bean") || fullPackage.endsWith(".entity") || fullPackage.endsWith(".beans") || fullPackage.endsWith(".entities")); } private static String generateTestMethod(String methodName, Map methodMap) { StringBuilder methodBuilder = new StringBuilder(); String className = (String) methodMap.get("className"); Object[] methodObj = (Object[]) methodMap.get(methodName); Class> returnType = (Class>) methodObj[0]; Class[] paramTypes = (Class[]) methodObj[1]; List > paramTypeList = Arrays.asList(paramTypes); List paramTypeParam = Lists.newArrayList(); Map basicTypeMap = Maps.newHashMap(); basicTypeMap.put("STRING", "\""+RandomStringUtils.randomAlphabetic(3)+"\""); basicTypeMap.put("INT", "0"); basicTypeMap.put("INTEGER", "0"); basicTypeMap.put("LONG", "1L"); basicTypeMap.put("DOUBLE", "1D"); basicTypeMap.put("SHORT", "1"); basicTypeMap.put("FLOAT", "1F"); basicTypeMap.put("BOOLEAN", "true"); basicTypeMap.put("BYTE", "0"); for (Class> paramClass : paramTypeList) { String paramClsStr = paramClass.getSimpleName().toUpperCase(); String paramValue = basicTypeMap.get(paramClsStr); if(paramValue != null) { paramTypeParam.add(paramValue); } else { paramTypeParam.add("null"); } } String paramStr = String.join(",", paramTypeParam); String returnCode = ""; String returnClassName = returnType.getSimpleName(); if (!returnClassName.equals("void")) { if(returnType.isArray()) { returnCode = returnType.getComponentType().getName() + "[]" + " result = "; } else { returnCode = returnType.getName() + " result = "; } } String methodBody = "\t@Test\r\n" + " public void test" + firstCharUpperCase(methodName) + "(){\r\n" + "\t\ttry{\r\n" + "\t\t\t" + returnCode + firstCharLowerCase(className) + "." + methodName + "(" + paramStr + ");\r\n" + "\t\t}catch (Exception e) {\n\t\t}\n" + "\n\t}\n\n"; methodBuilder.append(methodBody); return methodBuilder.toString(); } public static String getInitMethodString() { StringBuilder methodBuilder = new StringBuilder(); methodBuilder.append("\n"); methodBuilder.append("\t@Before\n"); methodBuilder.append("\t"); methodBuilder.append("public void initMocks(){\n"); methodBuilder.append("\t\tMockitoAnnotations.initMocks(this);\n"); methodBuilder.append("\t}"); methodBuilder.append("\n"); return methodBuilder.toString(); } private static String firstCharUpperCase(String input) { return input.substring(0, 1).toUpperCase().concat(input.substring(1)); } private static String firstCharLowerCase(String input) { return input.substring(0, 1).toLowerCase().concat(input.substring(1)); } private static String convertPathToPackageClass(Path sourcePath) { String fileName = ""; fileName = sourcePath.getFileName().toString().replace(".java", ""); String packageName = getPackageName(sourcePath); return packageName + "." + fileName; } private static String getPackageName(Path sourcePath) { try { Optional optional = Files.lines(sourcePath).findFirst(); if (optional.isPresent()) { return optional.get().replace("package ", "").replace(";", ""); } } catch (IOException e) { exitProcess(e); } return ""; } private static boolean isNotAbstract(Class> cls) { return !Modifier.isAbstract(cls.getModifiers()); } private static boolean isNotInterface(Class> cls) { return !Modifier.isInterface(cls.getModifiers()); } private static Set getClassPublicMethods(Class> cls) { Set methodSet = new HashSet<>(); Method[] publicMethods = cls.getDeclaredMethods(); for (Method m : publicMethods) { if (Modifier.isPublic(m.getModifiers()) || Modifier.isProtected(m.getModifiers())) { methodSet.add(m.getName()); } } return methodSet; } private static Map getMethodMap(Class> cls) { Map methodMap = new HashMap<>(); Method[] publicMethods = cls.getDeclaredMethods(); for (Method m : publicMethods) { if (Modifier.isPublic(m.getModifiers()) || Modifier.isProtected(m.getModifiers())) { // Return type Class> returnType = m.getReturnType(); // Method parameter Class[] paramTypes = m.getParameterTypes(); Object[] methodObj = new Object[] { returnType, paramTypes }; methodMap.put(m.getName(), methodObj); } } methodMap.put("className", cls.getSimpleName()); return methodMap; } private static Class> getSourceClass(String className) { Class> cls = null; try { cls = Class.forName(className); } catch (ClassNotFoundException e) { exitProcess(e); } return cls; } private static void exitProcess(Exception e) { e.printStackTrace(); System.exit(-1); } private static boolean notExists(Path path) { return !exists(path); } private static boolean exists(Path path) { return path.toFile().exists(); } }