Spring测试:如何访问独立配置文件中定义的MockBean?
Spring环境下Mock Bean并注入到BeanCollection的正确方式
你在Spring集成测试中尝试Mock BeanOne 并让BeanCollection使用该Mock实例,但遇到了以下问题:
- 测试类和配置类同时用
@MockBean会出现"重复Mock定义"错误 - 测试类用
@Autowired注入BeanOne无法进行Mock - 用
@Mock注解会出现两个不同的Mock实例,导致模拟结果不生效 - 不想使用纯Mockito方案,也不想开放配置类访问权限
核心思路
测试类中通过@MockBean定义的Mock实例会被Spring容器管理,配置类只需通过依赖注入获取该Mock,而非自行定义@MockBean,这样就能保证BeanCollection使用的Mock和测试类中操作的是同一个实例。
方案1:配置类通过方法参数注入Mock
修改BeanTestConfig,移除自行定义的@MockBean,改为在创建BeanCollection的方法中通过参数注入BeanOne:
public class BeanTestConfig { @Bean BeanTwo beanTwo() { return new BeanTwo(); } @Bean BeanCollection beanCollection(BeanOne beanOne, BeanTwo beanTwo) { return new BeanCollection(List.of(beanOne, beanTwo)); } }
测试类保持原有代码即可:
@ExtendWith(SpringExtension.class) @ContextConfiguration(classes = BeanTestConfig.class) class TestWithSeparateBeanConfig { @MockBean BeanOne beanOne; @Autowired BeanCollection beanCollection; @Test void test() { when(beanOne.sayHello(any())).thenReturn("Hello World"); assertEquals("Hello WorldBeanTwo says: Hello ugh", beanCollection.beansSayHello()); } }
方案2:配置类通过@Autowired注入Mock
如果偏好字段注入,也可以在配置类中用@Autowired获取BeanOne实例:
public class BeanTestConfig { @Autowired private BeanOne beanOne; @Bean BeanTwo beanTwo() { return new BeanTwo(); } @Bean BeanCollection beanCollection() { return new BeanCollection(List.of(beanOne, beanTwo())); } }
测试类代码同样无需修改。
问题原因解析
- 尝试1失败:测试类和配置类同时标记
@MockBean,Spring会尝试创建两个BeanOne的Mock实例,导致Bean定义冲突。 - 尝试2失败:如果配置类中自行定义了
@MockBean,测试类@Autowired获取的是配置类的Mock,但此时测试类再用@MockBean会引发冲突;若配置类用的是真实BeanOne,则无法Mock。 - 尝试3失败:
@Mock是Mockito独立创建的实例,未纳入Spring容器管理,配置类中的BeanOne是另一个实例(真实或Spring管理的Mock),因此测试类中设置的返回值对BeanCollection无效。
内容的提问来源于stack exchange,提问作者tm1701
相关产品推荐
相关产品推荐

