Java: Programmatically Compile and Unit Test Generated Java Source Code

In one of the projects I’m currently working on, I have to write a parser to translate a scripting language into Java code. This tutorial shows how you can unit test the generated Java code.

Let’s assume we have JavaCodeGeneratorService that looks something like this:-

public class JavaCodeGeneratorService {
    public String generate(String packageName, String className) {
        return "package " + packageName + ";" +
               "public class " + className + " {" +
               "    public boolean isOne(Integer i) {" +
               "      return i == 1;" +
               "    }" +

This service class generates Java source code as one big String. To unit test this code, we have to:-

  1. Programmatically compile the generated source code.
  2. Instantiate the class and invoke isOne(...) to get the returned value.
    1. So, the strategy here is to create an in-memory Java file object so that we don’t have to perform any clean ups. Then, we use reflection to invoke that API to get the returned value.

      package com.choonchernlim.epicapp;
      import com.choonchernlim.epicapp.service.JavaCodeGeneratorService;
      import org.apache.log4j.Logger;
      import static;
      import static org.junit.Assert.assertThat;
      import static;
      import org.junit.Test;
      import java.util.Arrays;
      import java.util.Locale;
      public class JavaCodeGeneratorServiceTest {
          // in-memory Java file object
          class InMemoryJavaFileObject extends SimpleJavaFileObject {
              private String contents = null;
              public InMemoryJavaFileObject(String className, String contents)
                      throws Exception {
                  super(URI.create("string:///" + className.replace('.', '/') +
                                   Kind.SOURCE.extension), Kind.SOURCE);
                  this.contents = contents;
              public CharSequence getCharContent(boolean ignoreEncodingErrors)
                      throws IOException {
                  return contents;
          private static Logger log = Logger.getLogger(SomeTest.class);
          JavaCodeGeneratorService javaCodeGeneratorService = new JavaCodeGeneratorService();
          public void testGeneratedCode() throws Exception {
              String packageName = "com.choonchernlim.epicapp.service.impl";
              String className = "HelloWorld";
              compile(className, javaCodeGeneratorService.generate(packageName, className));
              assertThat(invokeMethod(packageName, className, 1), is(true));
              assertThat(invokeMethod(packageName, className, 2), is(false));
              assertThat(invokeMethod(packageName, className, 0), is(false));
              assertThat(invokeMethod(packageName, className, -1), is(false));
          // creates an in-memory Java file object and compile it
          private void compile(String className, String code) throws Exception {
              // Create an in-memory Java file object
              JavaFileObject javaFileObject = new InMemoryJavaFileObject(className, code);
              JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
              StandardJavaFileManager fileManager = compiler.getStandardFileManager(null,
              // If the location of the new class files is not specified, it will be
              // placed at the project's root directory. Since this is a Maven project,
              // we will comply to the Maven structure and place the generated classes
              // under `target/classes` directory. Otherwise, we may get
              // `ClassNotFoundException` when we do the reflection.
              Iterable<File> files = Arrays.asList(new File("target/classes"));
              fileManager.setLocation(StandardLocation.CLASS_OUTPUT, files);
              // When shit happens, the `DiagnosticCollector` may reveal useful error messages
              DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
              JavaCompiler.CompilationTask task = compiler.getTask(null,
              boolean success =;
              // If there' a compilation error, display error messages and fail the test
              if (!success) {
                  for (Diagnostic diagnostic : diagnostics.getDiagnostics()) {
                      log.fatal("Code: " + diagnostic.getCode());
                      log.fatal("Kind: " + diagnostic.getKind());
                      log.fatal("Position: " + diagnostic.getPosition());
                      log.fatal("Start Position: " + diagnostic.getStartPosition());
                      log.fatal("End Position: " + diagnostic.getEndPosition());
                      log.fatal("Source: " + diagnostic.getSource());
                      log.fatal("Message: " + diagnostic.getMessage(Locale.getDefault()));
                  fail("Compilation failed!");
          // executes in-memory Java file object with input value
          private boolean invokeMethod(String classPackage, String className, Integer input) 
                  throws Exception {
              Class<?> clazz = Class.forName(classPackage + "." + className);
              return (Boolean) clazz.getDeclaredMethod("isOne", Integer.class)
                                    .invoke(clazz.newInstance(), input);

One thought on “Java: Programmatically Compile and Unit Test Generated Java Source Code

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s