tags:

views:

445

answers:

2

I have a project that builds with maven2 and runs a series of JUnit test cases against the code. This has worked fine up until this point, where I now have 2 tests that must run in a certain sequence for things to work correctly, let's say TestA and Test (A then B). Unfortunately, maven2 doesn't understand this, so I'm looking for a way of convincing it that it needs to run the tests in this order.

The problem is that I'm setting some final static fields in TestB, but I'm doing this from TestA, which itself uses those fields, and successful execution of the test depends on those fields being set to their new values (there is absolutely no way around this, otherwise I would have taken that road long before now). So, it is imperative that TestA loads first, and it will of course cause TestB to be loaded when tries to access it. However, maven2 has decided that it will run TestB then TestA, which means those final fields are already set and cannot be changed.

So what I'm looking for is either a way to specify the order in which the tests are executed (A then B, every time), or a way to easily cause TestB to be reloaded by whichever classloader that JUnit uses.

EDIT - one other option might be some option like the old JUnit GUI tool has, that causes all classes to be reloaded for each test. I have looked and looked and not found such a flag in the maven junit plugin, if such a thing exists, then that would also work.

+2  A: 

Fork mode can force each test to run in its own JVM so every class is re-loaded for each test.

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <configuration>
      <forkMode>pertest</forkMode>
    </configuration>
  </plugin>
sal
+1  A: 

The test order in JUnit is intentionally undefined, this is not a Maven issue and it's probably just luck that your tests were running OK up until now.

Sal's answer addresses your question directly, however forking the JVM on each test for large test counts can hugely increase your build time.

An alternative approach would be to use a testing library such as PowerMock (it currently works with EasyMock and Mockito) to clear the static fields in TestB's initialisation, this avoids the need for any JVM forking, and ensures your tests are portable.

From the PowerMock website:

PowerMock is a framework that extend other mock libraries such as EasyMock with more powerful capabilities. PowerMock uses a custom classloader and bytecode manipulation to enable mocking of static methods, constructors, final classes and methods, private methods, removal of static initializers and more. By using a custom classloader no changes need to be done to the IDE or continuous integration servers which simplifies adoption. Developers familiar with EasyMock will find PowerMock easy to use, since the entire expectation API is the same, both for static methods and constructors. PowerMock extends the EasyMock API with a small number of methods and annotations to enable the extra features. From version 1.1 PowerMock also has basic support for Mockito.

Rich Seller
sal
@sal agreed, if the number of tests is small, there is minimal overhead and your answer addresses the problem. I wouldn't introduce a new testing framework to address a single issue, but if there are multiple instances, it is worth considering. I thought I'd upvoted your answer at the time, I shall correct that now
Rich Seller
Using the pertest option in maven was the solution I eventually landed on, but I like the idea of using the libraries you mentioned. I will take a look. I was concerned about performance/build time overhead when I arrived at that conclusion before, and yes, there are more than 2 tests. Those 2 just happen to be the only ones where the order matters.
Troy Nichols