我正在使用 JUnit 编写一些测试用例。我需要初始化一些静态变量,这些变量将用于该类中的所有测试用例。
为此,我可以使用
- 静态初始化程序块或
- 静态方法
@BeforeClass
使用一个比另一个有什么优势?
@BeforeClass
初始化程序或static
初始化程序有非常不同的语义。
静态初始化程序由 JVM 调用,而不是由 JUnit 调用。如果在静态初始化程序中抛出异常,测试框架可能无法捕获和报告异常。此外,与方法相比,静态初始化程序的调用时间没有明确定义@BeforeClass
。每个类加载器在第一次实际使用时仅运行一次,例如访问静态属性、静态方法或其构造函数之一。有时,可能很难弄清楚这将是什么时候。(如果你不使用继承:你可能有一天或某个同事会重构你的测试用例。如果不是今天,选择静态初始化器可能会在未来引入令人讨厌的错误。)
另一方面,@BeforeClass
在每个类的测试运行之前运行。如果一个类要接受不同的测试,例如由于基于继承的测试,static
初始化程序将只在使用这个类的第一个测试时运行。这意味着您使您的测试订单依赖于您永远不想要的东西。
请注意,这两个选项之间的语义差异大于使用@Before
或测试构造函数之间的差异。作为最后一个论点,请考虑注释的文献价值。它使您的意图更具可读性。
此规则的唯一例外是不可变常量。这些应该在他们的声明中初始化,以保持您的代码简洁并尊重编译时间常数。但是,如果您的值是可变的,则根本不应该使用static
值。同样,在测试中更改的可变值会为您的测试引入顺序依赖性,这是要避免的。
TL;DR:使用@BeforeClass
!
在决定是否使用静态初始化块或时,可以考虑以下几点@BeforeClass
:
@BeforeClass
是 的对手@AfterClass
。因此,如果您进行需要稍后清理的初始化(例如打开外部资源),最好(从语义的角度)使用带注释的方法。@BeforeClass
,因为您不必捕获并将其包装到未经检查的异常中。private static final String VARIABLE
),您将别无选择,只能使用静态初始化块或静态方法。SO上有一个相关的帖子:单元测试-在JUnit 4 Java中使用@BeforeClass和使用实例或静态变量有什么区别?
如果两者兼而有之static
,final
那么您只有一个选择:静态初始化程序。
编译器将阻止您从方法内部写入最终字段,无论是否静态。
编辑:好的,你已经从你的问题中删除了“最终”这个词。在这种情况下,它几乎没有什么区别。静态初始化器将运行一次;@BeforeClass 方法也是如此。只需选择您认为更具可读性的一个。
这不是完全相同的行为。 @BeforeClass
每次运行测试时运行,静态初始化器仅在加载类时运行一次。如果您的测试运行程序使用相同的类加载器,那么在 的情况下@BeforeClass
,您将重新运行静态变量的初始化。这取决于你想在这里实现什么。