如何使用Java注解处理器生成测试代码并指定输出目录?
我目前已在项目中成功使用Java注解处理器基于注解生成代码,具体通过AbstractProcessor实现,代码输出逻辑如下:
Filer filer = processingEnv.getFiler(); JavaFileObject sourceFile = filer.createSourceFile(fullyQualifiedName); try (Writer writer = sourceFile.openWriter()) { javaFile.writeTo(writer); }
该实现会将Java文件生成至build/generated/sources/annotationProcessor/java/main目录,完全符合当前需求。
现在我希望新增代码生成逻辑,基于src/main/java中的内容生成供测试使用的代码,要求生成的源码存放在:
build/generated/sources/annotationProcessor/java/test
但我未在ProcessingEnvironment或AbstractProcessor中找到指定源码集的配置选项,请问使用Java注解处理器生成测试代码的标准方式是什么?
Java注解处理器本身没有直接指定源码集的API,生成测试代码的核心思路是让处理器在测试编译阶段运行,而非主代码编译阶段,具体有两种标准实现方式:
方式一:通过构建工具配置(以Gradle为例)
在Gradle中,可单独为测试源码集配置注解处理器,让处理器在测试编译任务执行时运行,生成的代码会自动落入test对应的生成目录:
dependencies { // 主代码编译阶段使用的注解处理器 annotationProcessor 'your-processor-group:your-processor:version' // 测试代码编译阶段使用的注解处理器 testAnnotationProcessor 'your-processor-group:your-processor:version' }
配置完成后,执行compileTestJava任务时处理器会再次运行,你可以在处理器中通过读取系统属性判断当前编译阶段,区分生成逻辑:
@Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { // 获取Gradle传递的源码集标识 String sourceSet = System.getProperty("gradle.sourceSet"); if ("test".equals(sourceSet)) { // 执行测试代码生成逻辑 generateTestCode(roundEnv); } else { // 执行主代码生成逻辑 generateMainCode(roundEnv); } return true; }
Gradle会在对应编译阶段自动设置gradle.sourceSet属性,你也可以自定义属性传递给处理器。
方式二:用自定义注解区分生成逻辑
若不想依赖构建工具配置,可在主代码中添加专门用于生成测试代码的注解(比如@GenerateTest),处理器识别到该注解时生成测试代码。需确保测试源码集能扫描到这些注解,且处理器在测试编译阶段运行。
注意:生成测试代码时,要保证类的包路径符合测试代码规范(比如在原包名后追加.test),避免和主代码类冲突。
内容的提问来源于stack exchange,提问作者Kevin

