在IntelliJ中测试Spring Boot 3集成MapStruct遇Bean缺失问题
Spring Boot 3 + MapStruct 测试时出现
NoSuchBeanDefinitionException的解决办法 问题背景
我在IntelliJ中测试一个返回DTO的Spring Boot 3控制器(用MapStruct做对象转换),主项目编译正常,但测试时一直抛出异常:
NoSuchBeanDefinitionException: No qualifying bean of type <my mapper type>
已做的配置操作:
- 编写测试配置类尝试扫描Mapper包,但无效:
@TestConfiguration @ComponentScan(basePackageClasses = EntityMapper.class) public class MapperConfig {}
- 测试类注解配置:
@ExtendWith(SpringExtension.class) @WebMvcTest({SiteController.class, MapperConfig.class}) public class SiteControllerTests { .... }
- Gradle依赖配置:
dependencies { implementation 'org.mapstruct:mapstruct:1.5.5.Final' annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.5.Final' ... }
- IntelliJ设置:启用「Enable annotation processing」,设置「Obtain processors from classpath」,MapStruct依赖设为Provided,已安装MapStruct插件,项目同时使用Lombok。
更新:Mapper定义
父接口:
public interface EntityMapper<D, E> { @Mapping(target = "id", ignore = true) @Mapping(target = "createdAt", ignore = true) @Mapping(target = "updatedAt", ignore = true) void updateEntityFromDto(@MappingTarget E entity, D dto); @Mapping(target = "id", ignore = true) @Mapping(target = "createdAt", ignore = true) @Mapping(target = "updatedAt", ignore = true) E fromDto(D dto); @Mapping(target = "id", ignore = true) @Mapping(target = "createdAt", ignore = true) @Mapping(target = "updatedAt", ignore = true) List<E> fromDto(List<D> dtoList); D toDto(E entity); List<D> toDto(List<E> entityList); }
具体业务Mapper:
@Mapper(componentModel = "spring") public interface SiteMapper extends EntityMapper<SiteDto, Site> { @Override @Mapping(source = "user.id", target = "userId") SiteDto toDto(Site site); @Override // 避免覆盖已有信息 @Mapping(target = "id", ignore = true) @Mapping(target = "createdAt", ignore = true) @Mapping(target = "updatedAt", ignore = true) @Mapping(target = "user", ignore = true) void updateEntityFromDto(@MappingTarget Site site, SiteDto siteDTO); }
解决步骤
1. 修正测试配置类的扫描范围
你的MapperConfig用EntityMapper.class作为扫描基准,但EntityMapper是父接口,MapStruct自动生成的Spring Bean是SiteMapperImpl,正确的扫描基准应该是实际带@Mapper注解的SiteMapper.class:
@TestConfiguration @ComponentScan(basePackageClasses = SiteMapper.class) public class MapperConfig {}
2. 直接在测试类导入Mapper Bean
@WebMvcTest默认只加载控制器相关Bean,不会自动扫描MapStruct生成的实现类。可以直接在测试类用@Import导入目标Mapper:
@ExtendWith(SpringExtension.class) @WebMvcTest(SiteController.class) @Import(SiteMapper.class) public class SiteControllerTests { .... }
3. 协调Lombok与MapStruct的注解处理器顺序
同时使用Lombok时,必须确保MapStruct处理器在Lombok之后执行,Gradle中补充配置:
dependencies { // 原有依赖 implementation 'org.mapstruct:mapstruct:1.5.5.Final' annotationProcessor 'org.projectlombok:lombok' annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.5.Final' // 添加绑定依赖 annotationProcessor 'org.projectlombok:lombok-mapstruct-binding:0.2.0' } tasks.withType(JavaCompile) { options.annotationProcessorPath = configurations.annotationProcessor options.compilerArgs += [ '-Amapstruct.defaultComponentModel=spring', '-Alombok.mapstruct.binding.enabled=true' ] }
4. 调整IntelliJ的依赖与注解处理设置
- 取消将MapStruct依赖设为
Provided,测试时需要该依赖在类路径中 - 执行
./gradlew clean build,确认MapStruct生成的SiteMapperImpl类出现在build/classes/java/main目录下 - 检查IntelliJ的「Annotation Processors」设置,确保「Processor path」选择「Module output」
内容的提问来源于stack exchange,提问作者jbrown
相关产品推荐
相关产品推荐

