You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在JUnit5 PER_CLASS生命周期下使用Mockito @InjectMocks

解决JUnit5 PER_CLASS生命周期下Mockito @Mock与@InjectMocks的注入问题

当测试类使用@TestInstance(TestInstance.Lifecycle.PER_CLASS)时,JUnit5只会创建一个测试类实例,但MockitoExtension默认会在每个测试方法执行前重新初始化@Mock对象,却不会将新创建的Mock重新注入到已存在的@InjectMocks实例中,导致后续测试方法仍使用第一次注入的旧Mock,新Mock无法生效,且无明确错误提示。

以下是两种简洁解决方案:

方案一:手动初始化Mock与注入(单次创建)

放弃Mockito注解的自动初始化逻辑,改用@BeforeAll在测试类初始化阶段仅执行一次Mock创建和注入,确保整个测试周期内Mock与被测试实例一一对应:

@ExtendWith(MockitoExtension::class)
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class MyTest {
    private lateinit var inner: InnerClass
    private lateinit var outer: OuterClass

    @BeforeAll
    fun setup() {
        inner = mock(InnerClass::class.java)
        // 方式1:直接构造注入(推荐,逻辑更直观)
        outer = OuterClass(inner)
        // 方式2:若依赖关系复杂,仍可使用Mockito注入API
        // outer = OuterClass()
        // MockitoAnnotations.openMocks(this).close()
    }

    @Test
    fun test1() { /* ... */ }

    @Test
    fun test2() { /* ... */ }
}

方案二:重置Mock状态而非重建实例

保留Mockito注解的自动注入能力,在每个测试方法执行前重置Mock的交互记录、存根状态,避免创建新Mock但不注入的问题:

@ExtendWith(MockitoExtension::class)
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class MyTest {
    @Mock
    private lateinit var inner: InnerClass

    @InjectMocks
    private lateinit var outer: OuterClass

    @BeforeEach
    fun resetMockState() {
        reset(inner)
    }

    @Test
    fun test1() { /* ... */ }

    @Test
    fun test2() { /* ... */ }
}

方案选择建议:

  • 若仅需保证每个测试的Mock状态干净,方案二更简洁,保留了Mockito注解的便利性;
  • 若必须在每个测试中使用全新Mock实例,方案一的手动构造注入逻辑更可靠。

内容的提问来源于stack exchange,提问作者tkruse

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 14:05:29