title: Generated Code Testing Incorporating PowerMock
body: <p>I ran into a snag recently.  I am writing some unit tests to exercise some portions of my library responsible for code generation.  The code takes an input of a configuration object, writes code using CodeModel, dumps these classes to String, then uses the Java 6 compiler api to compile them on the fly into usable classes.</p>
  
  <p>The snag I am hitting is one of the methods I am testing in the generated code uses a class with final methods (Android Bundle) and throws exceptions when used ("java.lang.RuntimeException: Stub!").  So, to get around this Ive used PowerMock to mock the final methods.  In this case, however, the compiler API throws a NPE.  I assume this is because of the facilities PowerMock is using behind the scenes, but I am not sure.</p>
  
  <p>Here's the exception:</p>
  
  <pre><code>at org.androidtransfuse.gen.classloader.MemoryFileManager.&lt;init&gt;(MemoryFileManager.java:11)
  at org.androidtransfuse.gen.classloader.MemoryClassLoader.&lt;init&gt;(MemoryClassLoader.java:16)
  at org.androidtransfuse.gen.ParcelableGeneratorTest.setup(ParcelableGeneratorTest.java:67)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
  at org.junit.internal.runners.MethodRoadie.runBefores(MethodRoadie.java:129)
  at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:93)
  at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:296)
  </code></pre>
  
  <p>MemoryFileManager.java:</p>
  
  <pre><code>class MemoryFileManager extends ForwardingJavaFileManager&lt;JavaFileManager&gt; {
      public final Map&lt;String, Output&gt; map = new HashMap&lt;String, Output&gt;();
  
      MemoryFileManager(JavaCompiler compiler) {
          super(compiler.getStandardFileManager(null, null, null));
      }
  
      @Override
      public Output getJavaFileForOutput
              (Location location, String name, JavaFileObject.Kind kind, FileObject source) {
          Output mc = new Output(name, kind);
          this.map.put(name, mc);
          return mc;
      }
  }
  </code></pre>
  
  <p>MemoryClassLoader.java (which uses MemoryFileManager):</p>
  
  <pre><code>public class MemoryClassLoader extends ClassLoader {
      private final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
      private final MemoryFileManager manager = new MemoryFileManager(this.compiler);
  
      public void add(String classname, String filecontent) {
          add(Collections.singletonMap(classname, filecontent));
      }
  
      public void add(Map&lt;String, String&gt; map) {
          List&lt;Source&gt; list = new ArrayList&lt;Source&gt;();
          for (Map.Entry&lt;String, String&gt; entry : map.entrySet()) {
              list.add(new Source(entry.getKey(), JavaFileObject.Kind.SOURCE, entry.getValue()));
          }
          this.compiler.getTask(null, this.manager, null, null, null, list).call();
      }
  
      @Override
      protected Class&lt;?&gt; findClass(String name) throws ClassNotFoundException {
          synchronized (this.manager) {
              Output mc = this.manager.map.remove(name);
              if (mc != null) {
                  byte[] array = mc.toByteArray();
                  return defineClass(name, array, 0, array.length);
              }
          }
          return super.findClass(name);
      }
  }
  </code></pre>
  
  <p>And a very basic test demonstrating this problem:</p>
  
  <pre><code>@RunWith(PowerMockRunner.class)
  @PrepareForTest(Parcel.class)
  public class ExampleTest {
  
      private static final String TEST_VALUE = "test value";
  
      String classToCompile =
              "import android.os.Parcel;\n" +
              "\n" +
              "public class ClassToCompile\n" +
              "{\n" +
              "\n" +
              "    private Parcel parcel;\n" +
              "}";
  
      @Test
      public void test() throws ClassNotFoundException, IOException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
          MemoryClassLoader classLoader = new MemoryClassLoader();
          classLoader.add("ClassToCompile", classToCompile);
          classLoader.loadClass("ClassToCompile");
      }
  }
  </code></pre>