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

如何在不使用@SpyBean注解的情况下以编程方式创建指定类的Mockito SpyBean?

如何在不使用@SpyBean注解的情况下以编程方式创建指定类的Mockito SpyBean?

嘿,这个需求我太懂了——不想让业务代码或者测试使用者手动加@SpyBean注解,想悄悄在底层搞定SpyBean的创建对吧?没问题,咱们直接用Mockito和Spring的上下文机制就能实现,给你两种实用的方法:

方法一:通过测试配置类注册SpyBean

这种方法适合需要在多个测试类中复用Spy的场景,咱们写个专门的测试配置类,把SpyBean注册到Spring上下文里:

import org.mockito.Mockito;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;

@TestConfiguration
public class SpyBeanAutoConfig {

    // 这里的Bean名称要和目标类的默认Bean名称一致(通常是类名首字母小写)
    @Bean
    public YourTargetClass yourTargetClass() {
        // 如果目标类有构造参数,可以先注入依赖再创建Spy
        // 比如:return Mockito.spy(new YourTargetClass(dependencyBean));
        
        // 简单场景下直接创建Spy实例
        return Mockito.spy(new YourTargetClass());
        
        // 如果想Spy Spring已经管理的原始Bean,也可以这么写:
        // return Mockito.spy(applicationContext.getBean(YourTargetClass.class));
    }
}

然后在你的测试类里,用@Import(SpyBeanAutoConfig.class)把这个配置引入,Spring就会自动用这个Spy实例替换掉原来的YourTargetClass Bean,业务代码或者测试类里直接注入就能用啦。

方法二:在测试代码中动态替换Bean

如果只是某个测试方法需要用到Spy,不想写额外的配置类,咱们可以直接在测试里操作Spring上下文,动态替换Bean:

import org.mockito.Mockito;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ConfigurableApplicationContext;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class YourBusinessTest {

    @Autowired
    private ConfigurableApplicationContext appContext;
    
    @Autowired
    private YourService yourService; // 这个类依赖了YourTargetClass

    private YourTargetClass targetSpy;

    @BeforeEach
    void setUp() {
        // 1. 获取上下文里的原始目标Bean
        YourTargetClass originalBean = appContext.getBean(YourTargetClass.class);
        // 2. 创建Spy实例
        targetSpy = Mockito.spy(originalBean);
        // 3. 替换上下文里的Bean
        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) appContext.getBeanFactory();
        registry.removeBeanDefinition("yourTargetClass");
        appContext.getBeanFactory().registerSingleton("yourTargetClass", targetSpy);
    }

    @Test
    void testBusinessLogic() {
        // 执行业务方法
        yourService.doBusiness();
        
        // 验证Spy的方法调用
        Mockito.verify(targetSpy).targetMethod();
    }
}

注意:如果目标类是Spring代理类(比如带@Transactional、@Async注解),直接Spy原始实例可能会导致代理失效,这时候一定要先获取Spring上下文里的代理实例再创建Spy哦。

备注:内容来源于stack exchange,提问作者Marian Klühspies

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.23 13:17:33