由于程序中调用了第三方的服务,但在单元测试的环境中并没有相关的类,导致单元测试报错;因此,通过在运行中动态创建需要的类来解决此问题。

  • 测试程序
//......
		
String serviceClass = "com.service.MyService";
try{
	Class.forName(serviceClass);
}catch(ClassNotFoundException e){
	String className = e.getMessage();
	try {
		if(serviceClass.equals(className)){
			dynamicCreateClass(className, getMyServiceText());
		}
	} catch (Exception ex) {
		ex.printStackTrace();
	}
}catch(Exception e){
	e.printStackTrace();
}

//......

//invoke MyService method...

在单元测试执行目标类的方法前,先尝试加载此类,如果类不存在则创建出来。

在实际场景中,捕获到的异常中不一定可以直接获取到ClassNotFoundException,可通过捕获Throwable异常来处理:

try{
	//...
}catch(Throwable t){
	Throwable cause = t.getCause();
	if(cause instanceof ClassNotFoundException){
		ClassNotFoundException noClassException = (ClassNotFoundException) cause;
		String className = noClassException.getMessage();
		try {
			if("com.service.MyService".equals(className)){
				dynamicCreateClass(className, getMyServiceText());
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}
}
  • Service类内容
private String getMyServiceText() {
	StringBuilder text = new StringBuilder();
	text.append("package com.service;");
	text.append("public class MyService {");
	text.append("	public static void sayHello(){");
	text.append("		System.out.println(\"Hello.\");");
	text.append("	}");
	text.append("}");
	return text.toString();
}
  • 动态创建类
private void dynamicCreateClass(String className, String classText) throws IOException, URISyntaxException{
	String path = getClass().getResource("/") + className.replaceAll("\\.", "/");
	File javaFile = new File(new URI(path + ".java"));
	File classFile = new File(new URI(path + ".class"));
	if(classFile.exists()){
		return;
	}
	String folderPath = path.substring(0, path.lastIndexOf('/'));
	File directory = new File(new URI(folderPath));
	if(!directory.exists()){
		directory.mkdirs();
	}
	if(!javaFile.exists()){
		javaFile.createNewFile();
	}
	try(FileWriter fileWriter = new FileWriter(javaFile)){
		fileWriter.write(classText);
	}
	JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
	try(StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null)){
		Iterable compilationunits = fileManager.getJavaFileObjects(javaFile);
		CompilationTask compilationTask = compiler.getTask(null, fileManager, null, null, null, compilationunits);
		compilationTask.call();
	}
}