在套件中使用@BeforeClass @Before 编写 JUnit 测试
Writing JUnit tests with @BeforeClass @Before in Suites
我正在使用 JUnit 4 测试带有内存数据库的后端系统。我正在使用 @BeforeClass @Before @After 和 @AfterClass.
到目前为止,它在 class 水平上运行良好。
@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
}
}
到目前为止,它在 class 水平上运行良好。
我可以(在 Eclipse 中)右键单击单个测试,它将 运行 @BeforeClass 然后 @Before.
我也可以(在 Eclipse 中)单击 class 本身,它只会 运行 @BeforeClass 一次然后 @Before 每次测试前。
.....但这个原则如何扩展到套件级别?
我想 运行 @BeforeClass 在我的套件中的所有 classes 之前。如果我这样写我的套件:
@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();
}
}
...我需要从所有测试 classes 中删除 @BeforeClass。这很烦人,因为我有很多测试 classes,我不想删除我的 @BeforeClass 因为我想单独测试它们。
我的基本意思是:
是否有简单的方法(在 IDE 中单击鼠标)在 (a) 方法级别、(b) class 级别和(c) 套件级别,同时保持会话级别的设置和拆卸过程?
所以我有一个类似的问题(数据库初始化、连接池、缓存数据等)需要在 运行 任何和所有测试之前完成一次。这通常在应用程序服务器启动时完成。对于需要这个的测试,我添加了一个基础 class:
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
}
}
并非所有测试都需要初始化堆栈,但那些需要初始化的测试将从该基础继承 class 并且它将正确处理初始化。希望对您有所帮助。
您需要的是通过不同的入口点管理全局状态。在您的 BeforeAll 或 AfterAll class 中,您可以保留一个静态引用,即一个 AtomicBoolean
来跟踪您是否已经执行过它。
现在的问题 - beforeAll 和 afterAll 有两个单独的 classes - class 应该负责那个标志。
因此我建议,您定义一个 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();
}
我正在使用 JUnit 4 测试带有内存数据库的后端系统。我正在使用 @BeforeClass @Before @After 和 @AfterClass.
到目前为止,它在 class 水平上运行良好。
@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
}
}
到目前为止,它在 class 水平上运行良好。
我可以(在 Eclipse 中)右键单击单个测试,它将 运行 @BeforeClass 然后 @Before.
我也可以(在 Eclipse 中)单击 class 本身,它只会 运行 @BeforeClass 一次然后 @Before 每次测试前。
.....但这个原则如何扩展到套件级别?
我想 运行 @BeforeClass 在我的套件中的所有 classes 之前。如果我这样写我的套件:
@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();
}
}
...我需要从所有测试 classes 中删除 @BeforeClass。这很烦人,因为我有很多测试 classes,我不想删除我的 @BeforeClass 因为我想单独测试它们。
我的基本意思是:
是否有简单的方法(在 IDE 中单击鼠标)在 (a) 方法级别、(b) class 级别和(c) 套件级别,同时保持会话级别的设置和拆卸过程?
所以我有一个类似的问题(数据库初始化、连接池、缓存数据等)需要在 运行 任何和所有测试之前完成一次。这通常在应用程序服务器启动时完成。对于需要这个的测试,我添加了一个基础 class:
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
}
}
并非所有测试都需要初始化堆栈,但那些需要初始化的测试将从该基础继承 class 并且它将正确处理初始化。希望对您有所帮助。
您需要的是通过不同的入口点管理全局状态。在您的 BeforeAll 或 AfterAll class 中,您可以保留一个静态引用,即一个 AtomicBoolean
来跟踪您是否已经执行过它。
现在的问题 - beforeAll 和 afterAll 有两个单独的 classes - class 应该负责那个标志。
因此我建议,您定义一个 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();
}