Here my test code:
public class Test1 {
@BeforeClass
public void setUp() {
EmbeddedTomcat.start();
}
// test methods...
@AfterClass
public void tearDown() {
EmbeddedTomcat.stop();
}
}
public class Test2 {
@BeforeClass
public void setUp() {
EmbeddedTomcat.start();
}
// test methods...
@AfterClass
public void tearDown() {
EmbeddedTomcat.stop();
}
}
// ...
As you can see, I duplicate the start and stop calls to embedded tomcat in each Test class. How can I avoid this duplication with JUnit ?
Requirement:
- The start and stop calls must be called ONCE for all test classes
JUnit 4.11
In addition to making a parent class that runs the @BeforeClass
and @AfterClass
. you can create a JUnit Rule. You can make your rule subclass ExternalResource which has methods to override for adding behavior before and after executions (class or tests).
public class EmbeddedTomcatServer extends ExternalResource {
...
@Override
protected void before() throws Throwable {
EmbeddedTomcat.start();
};
@Override
protected void after() {
EmbeddedTomcat.stop();
};
}
Then in your test use the @ClassRule
which runs the server's before()
and after()
methods during BeforeClass
and AfterClass
time.
public class Test1 {
@ClassRule
public static EmbeddedTomcatServer tomcat = new EmbeddedTomcatServer();
//tests as normal, no more @BeforeClass or @AfterClass
}
public class Test2 {
@ClassRule
public static EmbeddedTomcatServer tomcat = new EmbeddedTomcatServer();
//tests as normal, no more @BeforeClass or @AfterClass
}
This solution might be better than the using a parent class because you can use this Rule in any test without having to change the parent class.
EDIT
only running the start() and stop() once
It is a little unclear if you mean running the start and stop once per test class (as your original code using @BeforeClass and @AfterClass)
Or if you want to run start and stop only once over ALL of the tests across the all the test classes that are run.
If you want to do the latter, @ClassRules are helpful here too. Just create a test suite with the test classes to use and then put the ClassRule ONLY IN THE SUITE CLASS
@RunWith(Suite.class)
@SuiteClasses({ Test1.class, Test2.class })
public class AllTests {
@ClassRule
public static EmbeddedTomcatServer tomcat = new EmbeddedTomcatServer();
}
This will start tomcat when the AllTests suite starts and then stop tomcat when all the tests in the test suite have run.
If possible for your project, you can create a TestParent
class which defines these @BeforeClass
and @AfterClass
methods and make your Test1
and Test2
classes extend from it.
public class TestParent {
@BeforeClass
public void setUp() {
EmbeddedTomcat.start();
}
@AfterClass
public void tearDown() {
EmbeddedTomcat.stop();
}
}
public class Test1 extends TestParent {
//...
}
public class Test2 extends TestParent {
//...
}