java单元测试代码生成器

最近在学习jdk源码,打算把所有常用类的api熟悉一遍,通过编写单元测试的方式跑一遍,了解每一个api的用途,刚开始机构类是手写单测代码,但是效率很低,于是花了机构消失自己写了一个代码生成器,效率提高了很多,思想通用,下面附上代码

首先需要引入几个jar包(自行百度下载):

  • freemarker-2.3.27-incubating.jar
  • jdom2-2.0.6.jar
  • commons-lang3-3.7.jar

下面是项目结构:

java单元测试代码生成器_第1张图片

下面是生成器代码:

package test.java.generator;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;

/**
 * 代码生成器
 *
 */
public class CodeGenerator {
	/**
	 * 包路径
	 */
	private static final String BASE_PACKAGE = "test";//项目中代码根路径


	private String author;//注释中作者名称

	private String sourceClass="";//源类全路径

	private  String templateName="";//模板名称
	//项目根路径
	private final String rootSrcPath = getClass().getResource("/").getPath().replace("/out/production/jdk-source/","/src/");
	//模板路径
	final String templateDir = rootSrcPath + "test/java/generator/template";

	public CodeGenerator(String author, String sourceClass, String templateName) {
		this.author = author;
		this.sourceClass=sourceClass;
		this.templateName=templateName;
	}

	public void run() {
		try {
			//反射获取源class对象
			Class sourceGalss=Class.forName(sourceClass);
			//生成目标测试类
			generate(sourceGalss, templateName);
		}
		catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) throws ClassNotFoundException {
		//初始化代码生成器及执行
		CodeGenerator codeGenerator=new CodeGenerator("zqw","java.util.concurrent.atomic.AtomicIntegerFieldUpdater","test");
		codeGenerator.run();

	}
	/**
	* 使用freemarker模板工具生成目标代码
	 * void
	 * @throws
	 * @date 2020/6/17 22:28
	 */
	private void generate(Class sourceGalss, String templateName)
			throws IOException, TemplateException {
		//freemarker配置
		Configuration cfg = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
		//设置freemarker模板路径
		cfg.setDirectoryForTemplateLoading(new File(templateDir));
		cfg.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER);
		//获取模板对象
		Template template = cfg.getTemplate(templateName + ".ftl", "UTF-8");

		// 定义模板数据
		Package sourcePackage=sourceGalss.getPackage();
		Map data = new HashMap<>();
		//是否抽象类
		if (Modifier.isAbstract(sourceGalss.getModifiers())){
			data.put("isAbstract","1");
		}else {
			data.put("isAbstract","0");
		}
		//是否接口
		if (Modifier.isInterface(sourceGalss.getModifiers())){
			data.put("isInterface","1");
		}else {
			data.put("isInterface","0");
		}
		data.put("basePackage", BASE_PACKAGE+"."+sourcePackage.getName());
		data.put("realPackage", sourcePackage.getName());
		data.put("author", author);
		Method[] methods=sourceGalss.getDeclaredMethods();
		List methodNameList=new ArrayList<>();
		for (int i = 0; i < methods.length; i++) {
			Method methods1=methods[i];
			if (Modifier.isPublic(methods1.getModifiers())){
				methodNameList.add(methods1.getName().substring(0,1).toUpperCase()+methods1.getName().substring(1));
			}
		}

		Constructor[] constructors=sourceGalss.getDeclaredConstructors();
		List constructorList=new ArrayList<>();
		int count=0;
		for (int i = 0; i < constructors.length; i++) {
			Constructor constructor=constructors[i];
			if (Modifier.isPublic(constructor.getModifiers())){
				constructorList.add(count++);
			}
		}
		data.put("methods",methodNameList);
		data.put("constructorList",constructorList);
		data.put("date", DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
		data.put("className", sourceGalss.getSimpleName());


		// 输出文件

		String fileName = sourceGalss.getSimpleName().substring(0, 1).toUpperCase() + sourceGalss.getSimpleName().substring(1);
		final String outFile =
				rootSrcPath +  BASE_PACKAGE.replace(".", "/") + "/"  +sourcePackage.getName().replace(".","/")+"/"+
						fileName + "Test.java";
		final String outFilePath=rootSrcPath +  BASE_PACKAGE.replace(".", "/") + "/"  +sourcePackage.getName().replace(".","/");
		File filePath=new File(outFilePath);
		if (!filePath.exists()){
			filePath.mkdirs();
		}
		Writer out = new FileWriter(outFile);
		template.process(data, out);

		System.out.println(templateName + "文件生成成功:" + outFile);
	}

}

下面是模板文件代码:

package ${basePackage};


import ${realPackage}.${className};
import org.junit.Test;

/**
 * ${className}的测试类
 *
 * @author ${author}
 * @date ${date}
 */
public class ${className}Test {
<#if (isAbstract == "1")>
    //abstract

<#if (isInterface == "1")>
    //interface

    <#if (isAbstract != "1")&&(isInterface != "1")>
    <#list constructorList as count>
        @Test
        public void testConstruct${count}()throws Exception{
        ${className} testObj=new ${className}();
        }
    
    <#list methods as method>
        @Test
        public void test${method}(){
        ${className} testObj=new ${className}();
        }
    
    

}

 

你可能感兴趣的:(jdk源码解析)