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