【问题标题】:How to use constructor injection in Mapstruct's mapper?如何在 Mapstruct 的映射器中使用构造函数注入?
【发布时间】:2020-06-04 07:13:17
【问题描述】:

在某些映射器类中,我需要使用自动装配的 ObjectMapper 将 String 转换为 JsonNode 或 verse-vera。我可以通过使用带有@autowired 的字段注入来实现我的目标。但它不适合单元测试,所以我想尝试使用构造函数注入。

我当前使用字段注入的工作代码:

@Mapper(componentModel = "spring")
public class CustomMapper {
  @autowired
  ObjectMapper mapper;
}

我尝试将其转换为构造函数注入,以便在单元测试中提供构造函数参数:

@Mapper(componentModel = "spring")
public class CustomMapper {
  ObjectMapper mapper;

  public CustomMapper(ObjectMapper mapper) {
    this.mapper = mapper;
  }
}

但我在编译过程中收到Constructor in CustomMapper cannot be applied to the given type 错误。 我如何解决它?或者还有其他更好的方法可以在 Mapstruct 中将 String 映射到 JsonNode 吗?

【问题讨论】:

    标签: java spring-boot dependency-injection mapstruct


    【解决方案1】:

    构造函数注入不能在映射器定义中使用。仅在映射器实现中。

    但是,对于单元测试,我建议您使用 setter 注入。

    您的映射器将如下所示:

    @Mapper( componentModel = "spring") 
    public class CustomMapper {
    
        protected ObjectMapper mapper;
    
    
        @Autowired
        public void setMapper(ObjectMapper mapper) {
            this.mapper = mapper;
       } 
    
    } 
    

    【讨论】:

      【解决方案2】:

      1)MapStruct 有很好的特性:

      @Mapper(componentModel = "spring", uses ={ObjectMapper.class}, injectionStrategy = InjectionStrategy.CONSTRUCTOR)
      

      2)你可以这样做:

      @Mapper(componentModel = "spring")
      @RequiredArgsConstructor //lombok annotation, which authowire your field via constructor
      public class CustomMapper {
        private final ObjectMapper mapper;
      }
      

      但是你仍然可以通过字段来做到这一点。在这两种情况下,你都应该在测试中模拟它。请记住使用@InjectMocks

      public CustomMapperTest {
         @InjectMocks
         private CustomMapper customMapper;
         @Mock
         private ObjectMapper objectMapper
      
         @BeforeEach
         void setUp() {
            customMapper= new CustomMapperImpl();
            MockitoAnnotations.initMocks(this);
            when(objectMapper.map()).thenReturn(object);
         }
      
         @Test
         void shouldMap() {
            Object toObject = customerMapper.map(fromObject);
            assertThat(toObject)
              .hasFieldWithValue("fieldName", fromObject.getField());
         }
      }
      

      【讨论】:

      • 第二种情况不起作用。 MapStruct 不识别参数化构造函数,它会在没有显式构造函数调用的情况下生成实现,从而导致编译错误。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-05-05
      • 1970-01-01
      • 1970-01-01
      • 2021-06-06
      • 1970-01-01
      • 1970-01-01
      • 2017-11-03
      相关资源
      最近更新 更多