为何大家使用@Before而非@BeforeClass配合Mockito initMocks?
这是个很棒的问题!核心原因其实是测试隔离性和执行速度的权衡——而单元测试的基本原则,会让绝大多数人优先选择前者。具体来说:
JUnit实例生命周期的限制
默认情况下,JUnit 4会为每个测试方法创建一个全新的测试类实例。这么做的目的很明确:让每个测试完全独立,不会因为前一个测试修改了实例状态,而干扰后续测试的结果。
但@BeforeClass标记的方法是静态方法,只会在类加载时执行一次,而且根本无法访问测试类的非静态字段。如果你想在@BeforeClass里调用MockitoAnnotations.initMocks(this),根本行不通——static方法里没有可传递的this实例。除非你把所有mock字段都改成static,但这样一来,所有测试方法都会共享同一个mock实例,测试之间的状态会互相污染(比如一个测试设置的mock返回值,会被下一个测试继承),彻底破坏了测试的独立性。测试隔离性是单元测试的核心
虽然@BeforeClass确实能减少初始化次数、提升执行速度,但单元测试的首要目标是可靠、可重复。如果测试之间互相干扰,出现偶发的失败,排查问题的成本会远远超过那点速度提升。所以大多数团队都会优先保证测试的隔离性,选择用@Before在每个测试实例创建后初始化mock,确保每个测试都有干净的mock环境。Mockito有更省心的替代方案
其实现在很多人早就不用手动写MockitoAnnotations.initMocks(this)了。Mockito提供了更便捷的自动初始化方式:- JUnit 4可以直接用
@RunWith(MockitoJUnitRunner.class) - JUnit 5则用
@ExtendWith(MockitoExtension.class)
这些注解会自动为每个测试实例初始化mock,既省去了手动编写setup方法的麻烦,又天然保证了每个测试的mock都是独立的,完美兼顾了便捷性和隔离性。
- JUnit 4可以直接用
总结下来:@BeforeClass虽然快,但会破坏测试隔离性——而隔离性是单元测试的基础,这就是为什么大家普遍更愿意用@Before,或者直接用Mockito的自动初始化注解。
内容的提问来源于stack exchange,提问作者Diana Zaburina

