如何为通过Spring注入的mapstruct抽象映射器编写Junit测试

如何为通过Spring注入的mapstruct抽象映射器编写Junit测试,spring,unit-testing,junit,spring-test,mapstruct,Spring,Unit Testing,Junit,Spring Test,Mapstruct,我正在使用MapStruct,MapStruct-jdk8版本1.1.0.Final并定义通过Spring注入的抽象类 我正在研究如何通过Junit测试来测试它们? 我有一个基本的主映射器,将使用2个子映射器 @Mapper(componentModel = "spring", uses = {SubMapper1.class, SubMapper2.class}) public abstract class MainMapper { @Mapping(target = "field1",

我正在使用MapStruct,MapStruct-jdk8版本1.1.0.Final并定义通过Spring注入的抽象类

我正在研究如何通过Junit测试来测试它们? 我有一个基本的主映射器,将使用2个子映射器

@Mapper(componentModel = "spring", uses = {SubMapper1.class, SubMapper2.class})
public abstract class MainMapper {

  @Mapping(target = "field1", qualifiedByName = {"MyMapper2Name", "toEntity"})
  public abstract MyEntity toEntity(MyDto pDto);

  public MyDto fromEntity(MyEntity pEntity) {
     // Specific code, hence why I use Abstract class instead of interface. 
  }
}
我尝试了几种方法,但无法正确实例化映射器来测试它

@RunWith(SpringRunner.class)
public class MainMapperTest {

    private MainMapper service = Mappers.getMapper(MainMapper.class);

    @Test
    public void testToEntity() throws Exception {
.....
java.lang.RuntimeException:java.lang.ClassNotFoundException:找不到com.mappers.MainMapper的实现

我也尝试过通过@InjectMock,但也没有骰子

无法实例化名为“服务”的@InjectMocks字段。你没有 在字段声明中提供了实例,因此我尝试构造 例如。但是,我失败了,因为“MainMapper”类型为 抽象类

通过Spring@Autowired

原因: org.springframework.beans.factory.noSuchBean定义异常:否 “com.mappers.MainMapper”类型的合格bean可用:应为 至少1个符合autowire候选资格的bean。附属国 注释: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

我猜这可能与注释处理器有关,并且在启动测试时映射器没有生成。 我找到了

然而,类AnnotationProcessorStrunner似乎在1.2之前不可用,1.2还没有最终版本


因此,我的问题是如何编写Junit测试来测试我在代码中通过Spring注入使用的mapstruct抽象类映射器。

您遇到了多个问题:

  • 您应该仅将
    Mappers#getMapper(Class)
    与默认的
    componentModel
    一起使用,否则将无法正确实例化映射器。如果您在那里得到
    RuntimeException
    ,则表示未生成实现类。确保设置正确
  • 您需要针对实现
    mainmaperImpl
    进行测试,而不是针对抽象类
  • 如果您想使用Springbean进行测试,那么您需要使用正确的
    ComponentScan
    ,并确保实现和使用的映射器可以自动连接
  • 链接的类是错误的测试类,与测试用例无关。看看spring集成的集成测试用例


    AnnotationProcessorStrunner
    是我们测试的一部分,用于测试注释处理器,从一开始就存在。它不是发行版的一部分。

    为了回应@Richard Lewan的评论,这里是我如何使用2个子映射为抽象类ConfigurationMapper声明测试类的

    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = {ConfigurationMapperImpl.class, SubMapper1Impl.class, SubMapper2Impl.class})
    public class ConfigurationMapperTest {
    
    SpringBootTest
    注释中使用
    Impl
    生成的类,然后注入要测试的类:

    @Autowired
    private ConfigurationMapper configurationMapper;
    
    如果你需要更多的信息,请告诉我,但从那里可以很简单。 我没有嘲笑子映射,因为我最好一次测试所有映射过程。

    假设:

    • 您的
      MainMapper
      mapper被注入
      @组件转换器使用MainMapper
    您可以使用以下示例:

    @RunWith(SpringRunner.class)
    @ContextConfiguration
    public class ConsentConverterTest {
    
        @Autowired
        MainMapper MainMapper;
    
        @Autowired
        ConverterUsingMainMapper converter;
    
        @Configuration
        public static class Config {
    
            @Bean
            public ConverterUsingMainMapper converterUsingMainMapper() {
                return new ConverterUsingMainMapper();
            }
    
            @Bean
            public MainMapper mainMapper() {
                return Mappers.getMapper(MainMapper.class);
            }
        }
    
    
        @Test
        public void test1() {
            // ... your test.
        }
    
    }
    

    除了@TheBakker的答案之外:如果不需要整个SpringBoot堆栈,您可以使用
    @ContextConfiguration
    ,作为
    @SpringBootTest
    的一个更轻的替代方案。他的例子如下:

    @RunWith(SpringRunner.class)
    @上下文配置(类={
    ConfigurationMapperImpl.class,
    子映射1impl.class,
    子映射2Impl.class})
    公共类配置MapperTest{
    ...
    
    这是否意味着所有其他已自动连接的非映射器依赖项也需要在配置中定义为bean?我们需要在测试类中自动连接吗?我们不能使用@InjectMock吗?