简体   繁体   English

如何在 Mapstruct 的映射器中使用构造函数注入?

[英]How to use constructor injection in Mapstruct's mapper?

In some mapper classes, I need to use an autowired ObjectMapper to transform String to JsonNode or verse-vera.在某些映射器类中,我需要使用自动装配的 ObjectMapper 将String转换为JsonNode或 verse-vera。 I can acheive my goal by using the field injection with @autowired .我可以通过使用带有@autowired的字段注入来实现我的目标。 But it's not suitable for unit test so I'd like to try using the constructor injection.但它不适合单元测试所以我想尝试使用构造函数注入。

My current working code with the field injection:我当前使用字段注入的工作代码:

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

I try to convert it to the constructor injection so I can provide constructor argument in my unit test:我尝试将其转换为构造函数注入,以便我可以在单元测试中提供构造函数参数:

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

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

But I get a Constructor in CustomMapper cannot be applied to the given type error during compilation.但是我在编译期间Constructor in CustomMapper cannot be applied to the given type得到一个Constructor in CustomMapper cannot be applied to the given type错误。 How do I fix it?我如何解决它? Or is there other better way to map String to JsonNode in Mapstruct?或者还有其他更好的方法将String映射到JsonNode中的 JsonNode 吗?

Constructor injection cannot be used in the mapper definition.不能在映射器定义中使用构造函数注入。 Only in the mapper implementation.仅在映射器实现中。

However, for unit testing I'd suggest that you use setter injection.但是,对于单元测试,我建议您使用 setter 注入。

Your mapper will then look like:您的映射器将如下所示:

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

    protected ObjectMapper mapper;


    @Autowired
    public void setMapper(ObjectMapper mapper) {
        this.mapper = mapper;
   } 

} 

1)The MapStruct has good feature: 1)MapStruct 有很好的特性:

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

2)You could do it this way: 2)你可以这样做:

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

But still you could do it via field.You stiil should mock it in tests in both cases.但是你仍然可以通过 field.You 来做到这一点。在这两种情况下,你都应该在测试中模拟它。 Just remember to use @InjectMocks请记住使用@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());
   }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM