24

我正在使用 JUnit 编写一些测试用例。我需要初始化一些静态变量,这些变量将用于该类中的所有测试用例。

为此,我可以使用

  1. 静态初始化程序块或
  2. 静态方法@BeforeClass

使用一个比另一个有什么优势?

4

4 回答 4

27

@BeforeClass初始化程序或static初始化程序有非常不同的语义。

静态初始化程序由 JVM 调用,而不是由 JUnit 调用。如果在静态初始化程序中抛出异常,测试框架可能无法捕获和报告异常。此外,与方法相比,静态初始化程序的调用时间没有明确定义@BeforeClass每个类加载器在第一次实际使用时仅运行一次,例如访问静态属性、静态方法或其构造函数之一。有时,可能很难弄清楚这将是什么时候。(如果你不使用继承:你可能有一天或某个同事会重构你的测试用例。如果不是今天,选择静态初始化器可能会在未来引入令人讨厌的错误。)

另一方面,@BeforeClass在每个类的测试运行之前运行。如果一个类要接受不同的测试,例如由于基于继承的测试,static初始化程序将只在使用这个类的第一个测试时运行。这意味着您使您的测试订单依赖于您永远不想要的东西。

请注意,这两个选项之间的语义差异大于使用@Before或测试构造函数之间的差异。作为最后一个论点,请考虑注释的文献价值。它使您的意图更具可读性。

此规则的唯一例外是不可变常量。这些应该在他们的声明中初始化,以保持您的代码简洁并尊重编译时间常数。但是,如果您的值是可变的,则根本不应该使用static值。同样,在测试中更改的可变值会为您的测试引入顺序依赖性,这是要避免的。

TL;DR:使用@BeforeClass

于 2014-02-20T12:36:32.830 回答
3

在决定是否使用静态初始化块或时,可以考虑以下几点@BeforeClass

  1. @BeforeClass是 的对手@AfterClass。因此,如果您进行需要稍后清理的初始化(例如打开外部资源),最好(从语义的角度)使用带注释的方法。
  2. 如果您进行可能引发检查异常的复杂初始化,使用起来会更舒服@BeforeClass,因为您不必捕获并将其包装到未经检查的异常中。
  3. 如果您想使用具有复杂初始化的常量语义( private static final String VARIABLE),您将别无选择,只能使用静态初始化块或静态方法。

SO上有一个相关的帖子:单元测试-在JUnit 4 Java中使用@BeforeClass和使用实例或静态变量有什么区别?

于 2014-02-20T12:20:08.677 回答
1

如果两者兼而有之staticfinal那么您只有一个选择:静态初始化程序。

编译器将阻止您从方法内部写入最终字段,无论是否静态。

编辑:好的,你已经从你的问题中删除了“最终”这个词。在这种情况下,它几乎没有什么区别。静态初始化器将运行一次;@BeforeClass 方法也是如此。只需选择您认为更具可读性的一个。

于 2013-03-19T06:51:34.250 回答
0

这不是完全相同的行为。 @BeforeClass每次运行测试时运行,静态初始化器仅在加载类时运行一次。如果您的测试运行程序使用相同的类加载器,那么在 的情况下@BeforeClass,您将重新运行静态变量的初始化。这取决于你想在这里实现什么。

于 2013-03-19T06:53:49.053 回答