Reputation: 133
I have a lot of unit tests files that basically execute the same @BeforeClass
.
They start jetty web server, add some system properties.
So I'm wondering, is it possible to execute this only once, before unit test will be run?
Upvotes: 7
Views: 3280
Reputation: 1018
In addition to @Matt's answer about creating your own Runner (which I thought was the best approach) (see the answer here), I also created an additional JUnit test that validates that all of my tests use my Runner (in case one of my developers forgets):
PS: Note this depends on OpenPOJO.
@Test
public void ensureAllTestsUseEdgeRunner() {
for (PojoClass pojoClass : PojoClassFactory.getPojoClassesRecursively("your.base.package", null)) {
boolean hasTests = false;
for (PojoMethod pojoMethod : pojoClass.getPojoMethods()) {
if (hasTests = pojoMethod.getAnnotation(Test.class) != null) {
break;
}
if (hasTests = pojoMethod.getAnnotation(BeforeClass.class) != null) {
break;
}
if (hasTests = pojoMethod.getAnnotation(Before.class) != null) {
break;
}
if (hasTests = pojoMethod.getAnnotation(AfterClass.class) != null) {
break;
}
if (hasTests = pojoMethod.getAnnotation(After.class) != null) {
break;
}
}
if (hasTests) {
PojoClass superClass = pojoClass;
boolean hasRunWith = false;
while (superClass != null) {
// ensure it has the RunWith(EdgeJUnitRunner.class) annotation
RunWith runWithAnnotation = superClass.getAnnotation(RunWith.class);
if (runWithAnnotation != null && runWithAnnotation.value() == EdgeJUnitRunner.class) {
hasRunWith = true;
break;
}
superClass = superClass.getSuperClass();
}
if (!hasRunWith) {
throw new RuntimeException(pojoClass.getClazz().getName() + " should be annotated with @RunWith(EdgeRunner.class)");
}
}
}
}
Upvotes: 1
Reputation: 17649
You could use the @RunWith annotation:
@RunWith(JettyRunner.class)
public class MyAwesomeTest {
@Test
//...
}
And implement a new Runner
public class JettyRunner extends BlockJUnit4ClassRunner {
private static boolean initialized = false;
public JettyRunner(Class<?> klass) throws InitializationError {
super(klass);
synchronized (JettyRunner.class) {
if (!initialized) {
System.out.println("Let's run jetty...");
initialized = true;
}
}
}
}
I'm not sure if the synchronized block is really needed, just threw it in for good measure...
Upvotes: 10
Reputation: 47243
Do you run the test classes from a suite? A @BeforeClass
on the suite class will run once, before any tests run.
Upvotes: 0
Reputation: 6517
Maybe using a static initializer will do? Although it's not a very good idea to initialize some fields only once when running unit tests since some of the tests may drive the fields to an illegal state which will impede the running of the other tests.
Upvotes: 1