title: How can I configure maven project so that tests are not broken when main code changes?
body: <p>I noticed I can run into binary-compatibility problems between main source and test source in maven project configuration. When I change main code, and run  maven <code>test</code> target the main code is recompiled, but dependent tests aren't. This may lead to <code>java.lang.NoSuchMethodError</code>.</p>
  
  <p>Here is simple example:</p>
  
  <p>project structure:</p>
  
  <blockquote>
    <p>mavenbug<br>
    |- src/main/java/App.java<br>
    |- src/test/java/AppClassTest.java<br>
    |- pom.xml</p>
  </blockquote>
  
  <p>App.java:</p>
  
  <pre><code>package mavenbug;
  
  public class App {
  
      public static class BaseData {}
  
      public static class DerivedData extends BaseData {}
  
      public void method(BaseData data) {
          System.out.println("hello2 " + data.getClass().toString());
      }
  }
  </code></pre>
  
  <p>AppClassTest.java:</p>
  
  <pre><code>package mavenbug;
  
  import mavenbug.App.DerivedData;
  
  import org.junit.Test;
  
  public class AppClassTest {
  
      @Test
      public void test() {
          new App().method(new DerivedData());
      }
  
  }
  </code></pre>
  
  <p>pom.xml:</p>
  
  <pre><code>&lt;project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"&gt;
    &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
    &lt;groupId&gt;com.example&lt;/groupId&gt;
    &lt;artifactId&gt;mavenbug&lt;/artifactId&gt;
    &lt;version&gt;0.0.1-SNAPSHOT&lt;/version&gt;
    &lt;name&gt;mavenbug&lt;/name&gt;
    &lt;description&gt;simplest example of bug&lt;/description&gt;
    &lt;dependencies&gt;
       &lt;dependency&gt;
          &lt;groupId&gt;junit&lt;/groupId&gt;
          &lt;artifactId&gt;junit&lt;/artifactId&gt;
          &lt;version&gt;4.11&lt;/version&gt;
       &lt;/dependency&gt;
    &lt;/dependencies&gt;
    &lt;build&gt;
      &lt;resources /&gt;
      &lt;testResources /&gt;
      &lt;plugins&gt;
        &lt;plugin&gt;
          &lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;
          &lt;version&gt;2.5.1&lt;/version&gt;
          &lt;executions&gt;
            &lt;execution&gt;
              &lt;id&gt;default-compile&lt;/id&gt;
              &lt;phase&gt;compile&lt;/phase&gt;
              &lt;goals&gt;
                &lt;goal&gt;compile&lt;/goal&gt;
              &lt;/goals&gt;
            &lt;/execution&gt;
            &lt;execution&gt;
              &lt;id&gt;default-testCompile&lt;/id&gt;
              &lt;phase&gt;test-compile&lt;/phase&gt;
              &lt;goals&gt;
                &lt;goal&gt;testCompile&lt;/goal&gt;
              &lt;/goals&gt;
            &lt;/execution&gt;
          &lt;/executions&gt;
        &lt;/plugin&gt;
        &lt;plugin&gt;
          &lt;artifactId&gt;maven-surefire-plugin&lt;/artifactId&gt;
          &lt;version&gt;2.12.4&lt;/version&gt;
          &lt;executions&gt;
            &lt;execution&gt;
              &lt;id&gt;default-test&lt;/id&gt;
              &lt;phase&gt;test&lt;/phase&gt;
              &lt;goals&gt;
                &lt;goal&gt;test&lt;/goal&gt;
              &lt;/goals&gt;
            &lt;/execution&gt;
          &lt;/executions&gt;
        &lt;/plugin&gt;
      &lt;/plugins&gt;
    &lt;/build&gt;
    &lt;reporting /&gt;
  &lt;/project&gt;
  </code></pre>
  
  <p>Ok let's run maven <code>test</code>:</p>
  
  <pre><code>[INFO] Scanning for projects...
  [INFO] 
  [INFO] Using the builder org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder with a thread count of 1
  [INFO]                                                                         
  [INFO] ------------------------------------------------------------------------
  [INFO] Building mavenbug 0.0.1-SNAPSHOT
  [INFO] ------------------------------------------------------------------------
  [INFO] 
  [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ mavenbug ---
  [WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
  [INFO] Copying 0 resource
  [INFO] 
  [INFO] --- maven-compiler-plugin:2.5.1:compile (default-compile) @ mavenbug ---
  [WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
  [INFO] Compiling 1 source file to E:\workax4\mavenbug\target\classes
  [INFO] 
  [INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ mavenbug ---
  [WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
  [INFO] Copying 0 resource
  [INFO] 
  [INFO] --- maven-compiler-plugin:2.5.1:testCompile (default-testCompile) @ mavenbug ---
  [WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
  [INFO] Compiling 1 source file to E:\workax4\mavenbug\target\test-classes
  [INFO] 
  [INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ mavenbug ---
  [INFO] Surefire report directory: E:\workax4\mavenbug\target\surefire-reports
  
  -------------------------------------------------------
   T E S T S
  -------------------------------------------------------
  Running mavenbug.AppClassTest
  hello2 class mavenbug.App$DerivedData
  Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.063 sec
  
  Results :
  
  Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
  
  [INFO] ------------------------------------------------------------------------
  [INFO] BUILD SUCCESS
  [INFO] 
  </code></pre>
  
  <p>Nice, everything fine. Now change method signature in <code>App.java</code> to:</p>
  
  <pre><code>public void method(DerivedData data) {
  </code></pre>
  
  <p>This doesn't need any source change in <code>AppClassTest.java</code>, as call matches the new argument type.</p>
  
  <p>Let's re-run  maven target <code>test</code>:</p>
  
  <pre><code>[INFO] Scanning for projects...
  [INFO] 
  [INFO] Using the builder org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder with a thread count of 1
  [INFO]                                                                         
  [INFO] ------------------------------------------------------------------------
  [INFO] Building mavenbug 0.0.1-SNAPSHOT
  [INFO] ------------------------------------------------------------------------
  [INFO] 
  [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ mavenbug ---
  [WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
  [INFO] Copying 0 resource
  [INFO] 
  [INFO] --- maven-compiler-plugin:2.5.1:compile (default-compile) @ mavenbug ---
  [WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
  [INFO] Compiling 1 source file to E:\workax4\mavenbug\target\classes
  [INFO] 
  [INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ mavenbug ---
  [WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
  [INFO] Copying 0 resource
  [INFO] 
  [INFO] --- maven-compiler-plugin:2.5.1:testCompile (default-testCompile) @ mavenbug ---
  [INFO] Nothing to compile - all classes are up to date
  [INFO] 
  [INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ mavenbug ---
  [INFO] Surefire report directory: E:\workax4\mavenbug\target\surefire-reports
  
  -------------------------------------------------------
   T E S T S
  -------------------------------------------------------
  Running mavenbug.AppClassTest
  Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.063 sec &lt;&lt;&lt; FAILURE!
  test(mavenbug.AppClassTest)  Time elapsed: 0.007 sec  &lt;&lt;&lt; ERROR!
  java.lang.NoSuchMethodError: mavenbug/App.method(Lmavenbug/App$BaseData;)V
      at mavenbug.AppClassTest.test(AppClassTest.java:11)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      at java.lang.reflect.Method.invoke(Method.java:597)
      at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
      at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
      at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
      at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
      at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
      at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
      at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
      at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
      at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
      at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
      at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
      at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
      at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
      at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252)
      at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141)
      at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      at java.lang.reflect.Method.invoke(Method.java:597)
      at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)
      at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)
      at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)
      at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115)
      at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75)
  
  
  Results :
  
  Tests in error: 
    test(mavenbug.AppClassTest): mavenbug/App.method(Lmavenbug/App$BaseData;)V
  
  Tests run: 1, Failures: 0, Errors: 1, Skipped: 0
  
  [INFO] ------------------------------------------------------------------------
  [INFO] BUILD FAILURE
  [INFO] ------------------------------------------------------------------------
  [INFO] Total time: 2.071 s
  [INFO] Finished at: 2015-02-12T12:50:17+01:00
  [INFO] Final Memory: 38M/64M
  [INFO] ------------------------------------------------------------------------
  [ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.12.4:test (default-test) on project mavenbug: There are test failures.
  [ERROR] 
  [ERROR] Please refer to E:\workax4\mavenbug\target\surefire-reports for the individual test results.
  [ERROR] -&gt; [Help 1]
  [ERROR] 
  [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
  [ERROR] Re-run Maven using the -X switch to enable full debug logging.
  [ERROR] 
  [ERROR] For more information about the errors and possible solutions, please read the following articles:
  [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException
  </code></pre>
  
  <p>Opps. Test was looking for method with old param <code>BaseData</code> and it didn't found the same binary version.</p>
  
  <p>Can I change pom.xml somehow to avoid this? Or should I always use <code>clean test</code> as my target?</p>