Spring Boot+MapStruct+JUnit:服务测试中注入Mapper而非Stub
解决方案:在Spring Boot单元测试中使用真实MapStruct实现
一、纯单元测试(不加载Spring上下文,推荐)
这是单元测试的最优方案,无需启动Spring容器,直接使用真实Mapper实例:
1. 确保MapStruct在测试编译阶段生成实现类
检查pom.xml的注解处理器配置,确保测试阶段也能生成Mapper实现:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>11</source> <!-- 替换为你的JDK版本 --> <target>11</target> <annotationProcessorPaths> <path> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>1.5.3.Final</version> </path> <path> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>你的Lombok版本</version> </path> <!-- 可选:解决Lombok与MapStruct的兼容性问题 --> <path> <groupId>org.projectlombok</groupId> <artifactId>lombok-mapstruct-binding</artifactId> <version>0.2.0</version> </path> </annotationProcessorPaths> </configuration> </plugin> </plugins> </build>
2. 测试类直接实例化真实Mapper与服务类
利用Mappers.getMapper()获取真实Mapper实例,结合Mockito Mock其他依赖,直接创建服务类:
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; import org.mapstruct.factory.Mappers; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; @ExtendWith(MockitoExtension.class) public class StandardReservationServiceTest { @Mock private ReservationRepository reservationRepositoryMock; @Mock private ReservationRulesRepository reservationRulesRepositoryMock; // 真实的MapStruct实现实例 private final ReservationMapper reservationMapper = Mappers.getMapper(ReservationMapper.class); // 直接构造服务类,传入真实Mapper和Mock依赖 private final StandardReservationService service = new StandardReservationService( reservationMapper, reservationRepositoryMock, reservationRulesRepositoryMock ); @ParameterizedTest @EnumSource(ReservationSource.class) public void yourTestMethod(ReservationSource source) { // 编写测试逻辑 } }
二、集成测试(加载Spring上下文)
如果必须使用Spring容器,按以下方式修改:
1. 测试类配置
不要直接引用编译时生成的ReservationMapperImpl(编译前不存在,会导致clean报错),直接引用Mapper接口,Spring会自动扫描并注入其实现类:
@SpringBootTest(classes = {StandardReservationService.class, ReservationMapper.class}) public class StandardReservationServiceTest { @MockBean private ReservationRepository reservationRepositoryMock; @MockBean private ReservationRulesRepository reservationRulesRepositoryMock; @Autowired private ReservationMapper reservationMapper; // 真实的Mapper实现 @Autowired private StandardReservationService service; // 测试方法... }
2. 关键注意事项
- 确保Mapper接口所在包在Spring的扫描范围内
- 执行
mvn clean compile后,检查target/generated-sources/annotations目录下是否生成了ReservationMapperImpl类,确认注解处理器工作正常
常见问题排查
- IDE中找不到
ReservationMapperImpl:开启IntelliJ的「Enable annotation processing」(设置→Build, Execution, Deployment→Compiler→Annotation Processors) - Maven编译报错找不到Impl:检查注解处理器配置是否完整,执行
mvn clean test-compile验证测试阶段的代码生成
内容的提问来源于stack exchange,提问作者Yass
相关产品推荐
相关产品推荐

