Java动态创建类
由于程序中调用了第三方的服务,但在单元测试的环境中并没有相关的类,导致单元测试报错;因此,通过在运行中动态创建需要的类来解决此问题。
- 测试程序
//......
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();
}
}