Spring Boot集成测试中Mock MyBatis Mapper失败问题
解决Spring Boot集成测试Mock MyBatis Mapper时的Bean创建异常
问题原因
你手动Mock的ProductMapper接口Bean,没能阻止Spring通过MyBatis的MapperFactoryBean创建原Mapper实例。而MapperFactoryBean初始化时必须依赖sqlSessionFactory或sqlSessionTemplate,因此触发了参数缺失的异常。
解决方案
方法一:使用Spring Boot的@MockBean注解(推荐)
@MockBean是Spring Boot专为测试场景提供的注解,会自动替换容器中原有的ProductMapper Bean,完全跳过MyBatis的Mapper初始化逻辑,直接使用Mock实例。
修改后的测试代码:
@SpringBootTest(classes = ApiApplication.class, webEnvironment = WebEnvironment.DEFINED_PORT) @AutoConfigureMockMvc @TestPropertySource("classpath:test-application.properties") public class SpringGlue { @MockBean private ProductMapper productMapper; @BeforeEach void setupMock() { // 定义Mock逻辑 doAnswer(i -> { String id = i.getArgument(0); return Product.builder().id(id).name(id + "hello").build(); }).when(productMapper).getProductById(any()); } // 你的测试方法... }
方法二:调整@TestConfiguration的写法(较繁琐,不推荐)
如果坚持使用@TestConfiguration,需要确保MyBatis不会再尝试创建ProductMapper的代理Bean。可以通过@MyBatisScan排除该Mapper,同时保持你的Mock Bean为@Primary:
- 在主启动类或测试类上修改
@MyBatisScan,排除ProductMapper:
@SpringBootApplication @MyBatisScan(basePackages = "com.yourpackage.mapper", excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = ProductMapper.class)) public class ApiApplication { // ... }
- 保留原有的
@TestConfiguration配置:
@SpringBootTest(classes = ApiApplication.class, webEnvironment = WebEnvironment.DEFINED_PORT) @AutoConfigureMockMvc @TestPropertySource("classpath:test-application.properties") public class SpringGlue { @TestConfiguration public static class TestConfig { @Bean @Primary ProductMapper productMapper(){ ProductMapper productMapper = mock(ProductMapper.class); doAnswer(i -> { String id = i.getArgument(0); return Product.builder().id(id).name(id + "hello").build(); }).when(productMapper).getProductById(any()); return productMapper; } } }
注意事项
- 优先用
@MockBean,它是Spring Boot测试Mock Bean的标准方式,能避免很多配置冲突问题。 - 若用方法二,要确保
@MyBatisScan的排除规则正确,别影响其他Mapper的正常初始化。
内容的提问来源于stack exchange,提问作者Patan
相关产品推荐
相关产品推荐

