Giving JUnit something like TestNG.@BeforeSuite
JUnit is the Undisputed King of Java unit test Libraries.
TestNG has a way more compreensive lifecycle management using @Before/@After annotations. If you wanna know more, there is a good presentation about testNG on prezi. Slide 22 shows how @Before/After works.
For me, @BeforeSuite
is pretty much essential writting integrations test.
@BeforeSuite
: "the annotated method will be run before all tests in this suite have run."
And you can’t do that with JUnit!
People that do not understand what @BeforeSuite
does suggests using @BeforeClass
. Well, guess what, it ain’t the same.
The closest JUnit can get to @BeforeSuite is having a TestSuite annotated with @BeforeClass, but that means you need to manually keep track of your tests:
@RunWith(MySuite.class)
@SuiteClasses({FooTest.class, BarTest.class, BazTest.class});
Serious? 2016! For each new test, you need to "remember" to update this. NO WAY! This is so freaking insane!
A better way
So, what alternative can I offer? @ClassRule + singleton.
Yeah, I openned the laptop to suggest people: use a singleton.
Well, pick your poison, manual, error prone Suite or shameful singleton.
Example
On each test, I included my @RuleClass, pointing to a singleton:
public class Test[12] {
@ClassRule
public static SuiteRule rule = SuiteRule.INSTANCE;
@Test
public void setup() {
System.out.println("Test[12]");
}
}
And the rule would be something like this:
public static final SuiteRule INSTANCE = new SuiteRule();
private final AtomicBoolean initialized = new AtomicBoolean();
@Override
public Statement apply(Statement base, Description description) {
if (!initialized.get()) {
beforeSuite(description);
initialized.set(true);
}
return base;
}
protected void beforeSuite(Description description) {
System.out.println("Before suite");
}
Running this example printed this:
Before suite
Test1
Test2
No rocket science, quite the oposite, a very trivial piece of code, using design patterns that I don’t even like, but since I saw so many people asking for it and no good answer, I decided to document a better alternative.
The entire example is on github.