@SpringBootTest 与 MapStruct 需要 Impl

til*_*ias 2 java mapstruct spring-boot-test

我有以下测试:

@SpringBootTest(classes = {SomeService.class, DtoMapperImpl.class})
class SomeServiceTest {
Run Code Online (Sandbox Code Playgroud)

以及以下映射器:

@Mapper(componentModel = "spring")
public interface DtoMapper {
    EntityDto toDto(Entity entity);
}
Run Code Online (Sandbox Code Playgroud)

我不会更改包(这意味着DtoMapperImpl与DtoMapper位于同一包中)

一旦我将 Impl 更改为接口,我的测试就会失败:

@SpringBootTest(classes = {SomeService.class, DtoMapper.class})
class SomeServiceTest {
Run Code Online (Sandbox Code Playgroud)

引起:org.springframework.beans.factory.UnsatisfiedDependencyException:创建名称为“someService”的bean时出错:通过构造函数参数2表达的依赖关系不满足;嵌套异常是 org.springframework.beans.factory.NoSuchBeanDefinitionException:没有可用的“DtoMapper”类型的合格 bean:预计至少有 1 个符合自动装配候选资格的 bean。依赖注释:{}

您能建议解决这个问题的最佳方法吗?我正在使用 MapStruct 1.3.1.Final

Fil*_*lip 5

这个问题实际上与MapStruct无关,而是与如何SpringBootTest#classes使用有关。

in旨在提供用于在测试中加载的组件classesSpringBootTest

来自 JavaDoc:

用于加载ApplicationContext. 也可以使用 来指定@ContextConfiguration(classes=...)@Configuration如果没有定义显式类,则测试将在回退到搜索之前查找嵌套类@SpringBootConfiguration。返回:用于加载应用程序上下文的组件类

在你的情况下,你有 2 个课程:

  • SomeService- 我认为这是一个带有注释的类@Service,Spring 将正确加载它
  • DtoMapper- 这是 MapStruct 映射器,它是一个接口,而不是一个组件。您想要进行测试的组件是DtoMapperImpl

您有多种选择来解决此问题:

使用 Impl 类

您可以在您的 中使用DtoMapperImpl(Spring Component 类)SpringBootTest#classes,然后您的测试将加载正确的组件

使用自定义配置类来组件扫描您的映射器

@TestConfiguration
@ComponentScan("com.example.mapper")
public class MappersConfig {

}
Run Code Online (Sandbox Code Playgroud)

然后在你的SpringBootTest#classes. 例如

@SpringBootTest(classes = {SomeService.class, MappersConfig.class})
class SomeServiceTest {
   ...
}
Run Code Online (Sandbox Code Playgroud)