Hi Andrew,
TLDR version: it might be best *not* to use the example functionality in your test cases.
I've often wondered why jUnit's BeforeClass and AfterClass annotations are static - sometimes it causes issues. I believe that the rationale is that we shouldn't be sharing data between tests because it risks creating ordering effects - it's better to recreate all test data for each test case (or each "example" as we call them in concordion).
In fact, Martin Fowler (one of the jUnit authors) writes about this exact point:
I've also done some research and discovered that jUnit creates a new test object for *each* test case. It used to be that a concordion test had exactly one test case - now we have one per example. So a non-static before spec annotation might not work for you. Note that I have not observed this in my own jUnit usage so the jUnit behaviour might have changed over time.
eg: apparently the following code prints "0 0 0":
public class TestJunit
{
int count = 0;
@Test
public void testInc1(){
System.out.println(count++);
}
@Test
public void testInc2(){
System.out.println(count++);
}
@Test
public void testInc3(){
System.out.println(count++);
}
}
However, pragmatically :)
- I do like the idea of beforeProcessingSpecification and afterProcessingSpecification annotations. These are like Spring's @PostConstruct and @PreDestroy annotations. We could even have concordion:example="beforeProcessingSpecification" tags in the spec - like concordion:example="before" tags. However, I've looked at the code (including our junit integration) and it might be tricky to do cleanly.
- You are right that this.getClass().getName() will *not* work the same static methods as it does in non-static methods. You can get around this by having the static methods take a class parameter. But that won't work for @BeforeClass methods where you can't pass parameters. Sigh.
- One way to get around the @before annotation working differently is to create lazy initialisers. That way the initializers are only invoked once. Something like the following - but I can't figure out a good @AfterClass version.
public synchronized void before() {
if (!initialized) {
initialised= true;
... do whatever
}
- If you only have one example (ie: don't use the concordion:example tag) then @Before and @After will work as they did before :)
Hope that helps,
Tim