我正在使用JUnit 4来测试带有内存数据库的后端系统。我正在使用 @BeforeClass @Before @After 和 @AfterClass 。
到目前为止,它在课堂上一直很好。
@BeforeClass 包含很慢的数据库设置,但每个测试会话只需完成一次。
@Before 只是将板擦干净以进行下一个测试。非常快。
我的测试看起来像这样:
class CompanyTest {
@BeforeClass
public static void beforeAll() throws Exception {
BeforeAll.run(); //Setup In Memory Database!!! Very time intensive!!!
}
@Before
public void beforeTest() throws Exception {
BeforeTest.run(); //Setup data in database. Relatively quick
}
@Test
public void testCreateCompany() throws Exception {
///...
}
@Test
public void testDeleteCompany() throws Exception {
///...
}
@Test
public void testAdminCompany() throws Exception {
///...
}
@After
public void afterTest() {
AfterTest.run(); //clear data
}
@AfterClass
public static void afterAll() throws Exception {
AfterAll.run(); //tear down database
}
}
到目前为止,它在课堂上一直很好。
我可以右键单击(在Eclipse中)单个测试,它将运行 @BeforeClass ,然后运行 @Before 。
我也可以在类本身上单击(在Eclipse中),它将只运行一次 @BeforeClass ,然后在每次测试前运行 @Before 。
....但是该原则如何扩展到套件级别?
我想在我的Suite中的所有类之前运行@BeforeClass。如果我这样写我的套件:
@Suite.SuiteClasses({ CompanyTest.class, CustomerTest.class, SomeOtherTest.class, })
public class AllTests {
@BeforeClass
public static void beforeAll() throws Exception {
BeforeAll.run();
}
@AfterClass
public static void afterAll() throws Exception {
AfterAll.run();
}
}
...我需要从所有测试类中删除@BeforeClass。这很烦人,因为我有很多测试类,并且我不想删除@BeforeClass,因为我想单独测试它们。
我基本上要说的是:
是否有一种简单的方法(在IDE中单击鼠标)可以在(a)方法级别,(b)类级别和(c)套件级别测试JUnit测试,同时保持会话级别设置和拆卸过程?
答案 0 :(得分:1)
因此,我有一个类似的问题(数据库初始化,连接池,缓存的数据等),在运行任何和所有测试之前需要完成一次。通常在应用程序服务器启动时完成。对于需要这样做的测试,我添加了一个基类:
public class BaseInitializedTest {
private boolean isInitialized;
@BeforeClass
public static void init() {
doOnetimeInit();
// Do other per unique class initialization here
}
private static synchronized void doOnetimeInit() {
if (!isInitialized) {
// Do you one time init here
isInitialized = true;
}
}
@AfterClass
public static void deinit() {
// Cleanup
}
}
然后是需要初始化的测试:
public class SomethingTest extends BaseInitializedTest {
@Test
public testSomething() {
// Your test here
}
}
并非所有测试都需要初始化堆栈,但是那些测试会从该基类中进行初始化,并且将正确处理初始化。希望有帮助。
答案 1 :(得分:1)
您需要的是,全局状态是通过不同的入口点进行管理的。在您的BeforeAll或AfterAll类中,您可以保留静态引用,即AtomicBoolean
来跟踪您是否已经执行了它。
现在的问题-对于beforeAll和afterAll具有两个单独的类-哪个类应负责该标志。
因此,我建议您定义一个Rule
,其中包含所有用于设置和拆卸的逻辑(基本上是BeforeAll和AfterAll的所有代码),并管理用于跟踪初始化的全局状态。
基本上类似
class MyRule implements TestRule {
static final AtomicBoolean INITIALIZED = new AtomicBoolean();
@Override
public Statement apply(final Statement base, final Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
boolean needsTearDown = false;
try {
if (INITIALIZED.compareAndSet(false, true)) {
BeforeAll.run();
needsTearDown = true;
}
base.evaluate();
} finally {
if (needsTearDown) {
AfterAll.run();
INITIALIZED.set(false);
}
}
}
};
}
}
然后在您的测试和套件中添加
class YourTestOrSuite {
@ClassRule
public static MyRule rule = new MyRule();
}