Spring Boot从2.1升级到2.3后@MockBean对MyBatis仓库失效求助
Spring Boot 2.3升级后@MockBean对MyBatis Repository失效的解决办法
问题现象
将Spring Boot从2.1升级到2.3后,单元测试中用@MockBean模拟MyBatis的StockQuantityRepository时,服务类里注入的却是实际的代理实例($Proxy132),而非测试类中配置的Mock实例(StockQuantityRepository$MockitoMock$xxx),导致测试调用了真实数据库方法而失败,但@MockBean对Service、Controller等组件仍能正常工作。
测试类代码片段:
@MockBean private StockQuantityRepository stockQuantityRepository; Mockito.doReturn(lockedList) .when(stockQuantityRepository) .lockStockQuantityList(Mockito.anyList(), Mockito.anyInt());
服务类代码片段:
lockedStockList = stockQuantityRepository.lockStockQuantityList(processList, lockWaitTimeout);
问题原因
Spring Boot 2.3调整了MyBatis自动配置的Bean注册逻辑,MyBatis的Mapper代理Bean通过MapperFactoryBean动态创建,其注册时机晚于@MockBean的Bean替换逻辑,导致实际的Mapper代理覆盖了Mock实例。
解决办法
方案1:给@MockBean添加@Primary注解
在测试类的MockBean上加上@Primary,确保Mock实例的优先级高于MyBatis自动创建的代理Bean:
@MockBean @Primary private StockQuantityRepository stockQuantityRepository; // 原有Mock配置不变 Mockito.doReturn(lockedList) .when(stockQuantityRepository) .lockStockQuantityList(Mockito.anyList(), Mockito.anyInt());
方案2:手动创建MockBean并标记@Primary
如果方案1不生效,可通过@Bean方法手动创建Mock实例,强制让容器优先使用这个Mock:
@SpringBootTest public class YourTestClass { @Autowired private StockQuantityRepository stockQuantityRepository; @Autowired private YourService yourService; @Bean @Primary public StockQuantityRepository stockQuantityRepository() { return Mockito.mock(StockQuantityRepository.class); } @BeforeEach void setUp() { Mockito.doReturn(lockedList) .when(stockQuantityRepository) .lockStockQuantityList(Mockito.anyList(), Mockito.anyInt()); } }
方案3:使用@MyBatisTest(仅针对MyBatis单测场景)
如果测试只关注MyBatis相关逻辑,用@MyBatisTest替代@SpringBootTest,该注解会自动禁用不必要的自动配置,同时正确处理MockBean:
@MyBatisTest public class StockQuantityRepositoryTest { @MockBean private StockQuantityRepository stockQuantityRepository; @Autowired private YourService yourService; @Test void testLockStock() { Mockito.doReturn(lockedList) .when(stockQuantityRepository) .lockStockQuantityList(Mockito.anyList(), Mockito.anyInt()); // 执行测试逻辑 yourService.processStock(); // 验证调用 Mockito.verify(stockQuantityRepository).lockStockQuantityList(Mockito.anyList(), Mockito.anyInt()); } }
方案4:检查Mapper扫描配置
如果项目中自定义了@MapperScan注解,确保扫描路径正确,且没有和Spring Boot的自动配置冲突。避免在测试类中重复配置Mapper扫描,防止重复创建Bean。
内容的提问来源于stack exchange,提问作者Sandeep Kumar P K
相关产品推荐
相关产品推荐

