JUNIT:对于大量测试类只运行一次安装

我有一个课程,我用它作为unit testing的基础。 在这个类中,我初始化我的测试的整个环境,设置数据库映射,在多个表中输入许多数据库记录等。该类有一个带有@BeforeClass注释的方法来进行初始化。 接下来,我将该类扩展为具有@Test方法的特定类。

我的问题是,由于前面的类对于所有这些测试类完全相同,我如何确保它们仅对所有测试运行一次。 一个简单的解决方案是我可以将所有测试保持在一个类中。 但是,测试的数量很大,它们也是根据function头分类的。 所以他们位于不同的class级。 但是,由于它们需要完全相同的设置,因此它们inheritance了@BeforeClass。 因此,每个测试课程至少完成一次整个设置,总共花费的时间比我想要的多。

但是,我可以将它们全部放在一个包下的各种子包中,因此,如果有一种方法,我可以为该包中的所有测试运行一次设置,那就太棒了。

使用JUnit4测试套件,您可以执行以下操作:

@RunWith(Suite.class) @Suite.SuiteClasses({ Test1IT.class, Test2IT.class }) public class IntegrationTestSuite { @BeforeClass public static void setUp() { System.out.println("Runs before all tests in the annotation above."); } @AfterClass public static void tearDown() { System.out.println("Runs after all tests in the annotation above."); } } 

然后运行此类,就像运行普通测试类一样,它将运行所有测试。

JUnit不支持这一点,你必须使用标准的Java解决方案来实现单例:将公共设置代码移动到静态代码块中,然后在这个类中调用一个空方法:

  static { ...init code here... } public static void init() {} // Empty method to trigger the execution of the block above 

确保所有测试都调用init() ,例如我将它放入@BeforeClass方法。 或者将静态代码块放入共享基类中。

或者,使用全局变量:

  private static boolean initialize = true; public static void init() { if(!initialize) return; initialize = false; ...init code here... } 

您可以使用@BeforeClass方法创建一个BaseTest类,然后让所有其他测试inheritance它。 这样,当构造每个测试对象时,@ @BeforeClass被执行。

同时避免对所有测试套件执行一次,因为所有测试用例都应该是独立的。 @BeforeClass应该只执行一次测试用例,而不是测试套件。

为所有测试创建一个基类:

 public class BaseTest { static{ /*** init code here ***/ } } 

并且每个测试都应该inheritance它:

 public class SomeTest extends BaseTest { } 

如果您可以容忍将spring-test添加到项目中,或者您已经在使用它,那么一个好的方法是使用此处描述的技术: 如何使用Spring Test每个案例加载一次DBUnit测试数据

不确定是否有人仍在使用JUnit并尝试在不使用Spring Runner(也就是没有弹簧集成)的情况下修复它。 TestNG具有此function。 但这是一个基于JUnit的解决方案。

像每个线程操作一样创建RunOnce。 这将维护运行该运行的类的列表。

 public class RunOnceOperation { private static final ThreadLocal t = new ThreadLocal(); public void run(Function f) { if (t.get() == null) { t.set(Arrays.asList(getClass())); f.apply(0); } else { if (!((List) t.get()).contains(getClass())) { ((List) t.get()).add(getClass()); f.apply(0); } } } } 

回到你的unit testing

 @Before public beforeTest() { operation.run(new Function() { @Override public Void apply(Integer t) { checkBeanProperties(); return null; } }); } private void checkBeanProperties() { //I only want to check this once per class. //Also my bean check needs instance of the class and can't be static. } My function interface is like this: interface Function { O apply(I i); } 

使用此方法时,可以使用ThreadLocal对每个类执行一次操作。