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

Mockito @MockBean在新线程中二次调用失效问题排查

问题分析

你遇到的@MockBean在新线程中第二次调用返回null的问题,根源在于Spring Boot 1.5.x版本结合JUnit 4时,@MockBean生成的代理对象依赖线程局部上下文存储mock存根。当在主线程设置mock行为后,新线程第一次调用能读取到存根,但第二次调用时,线程上下文的mock状态已丢失,导致返回默认值null。

解决方案

针对这个问题,有以下几种可行的解决方式:

方案1:在新线程内设置mock存根

把mock行为的设置逻辑移到新线程内部,确保存根在当前线程上下文生效:

@Test
public void testInNewThread_work() {
    Thread t = new Thread(new Runnable() {
        public void run() {
            // 在新线程内设置mock行为
            DemoServiceMock.mockdoSomething(demoService);
            
            // 两次调用都会返回预期值
            String result = demoService.doSomething("324234");
            System.out.println("return in thread: " + result);

            String result2 = demoService.doSomething("324234");
            System.out.println("return2 in thread: " + result2);
        }
    });
    t.start();
    // 等待线程执行完成,避免测试提前结束
    try {
        t.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

方案2:手动创建mock并注入Spring上下文

放弃@MockBean,手动创建Mockito mock实例,通过@Primary标记优先注入,这样mock是全局线程安全的:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = DemoApplication.class)
public class DemoApplicationTests {

    @Autowired
    protected DemoService demoService;

    // 手动创建mock并标记为优先注入的Bean
    @Bean
    @Primary
    public DemoService demoServiceMock() {
        return Mockito.mock(DemoService.class);
    }

    @Test
    public void testInNewThread_work() {
        DemoServiceMock.mockdoSomething(demoService);

        Thread t = new Thread(new Runnable() {
            public void run() {
                String result = demoService.doSomething("324234");
                System.out.println("return in thread: " + result);

                String result2 = demoService.doSomething("324234");
                System.out.println("return2 in thread: " + result2);
            }
        });
        t.start();
        try {
            t.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

方案3:升级Spring Boot版本

Spring Boot 1.5.x属于老旧版本,后续2.x+版本已修复@MockBean在多线程场景下的线程上下文问题。如果项目允许,建议升级到Spring Boot 2.x及以上版本,无需修改代码即可解决该问题。

补充说明

原测试方法testInNewThread_notWork未等待新线程执行完成,可能导致测试提前结束,无法看到完整输出结果,建议添加t.join()确保线程执行完毕。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 21:30:19