JUnit-如何模拟MapStruct嵌套映射器

时间:2018-11-05 13:40:29

标签: spring-boot junit nested mapper mapstruct

当我为服务层类运行单元测试时,我收到了一个烦人的NPE。 此类使用MapStruct自动生成的映射器,该映射器内部使用另一个映射器(请参见Mapper批注中的“ uses”属性):

    Mapper(componentModel = "spring", uses = {UserMapper.class})
public interface CandidateMapper extends EntityMapper<CandidateDTO, Candidate> {



  @Mapping(target = "createdBy", ignore = true)
  @Mapping(target = "createdDate", ignore = true)
  @Mapping(target = "lastModifiedBy", ignore = true)
  @Mapping(target = "lastModifiedDate", ignore = true)
  @Mapping(target = "applications", ignore = true)
  Candidate toEntity(CandidateDTO candidateDTO);

  default Candidate fromId(Long id) {
    if (id == null) {
      return null;
    }
    Candidate candidate = new Candidate();
    candidate.setId(id);
    return candidate;
  }
}

我的UnitTest是:

    @RunWith(SpringRunner.class)
    public class CandidateServiceTest {

      private CandidateService candidateService;

      @MockBean
      private UserRepository userRepository;
      @MockBean
      CandidateRepository candidateRepository;
      @MockBean
      UserDetailsService userDetailsService;

      CandidateMapper candidateMapper = Mappers.getMapper(CandidateMapper.class);

      UserMapper userMapper = Mappers.getMapper(UserMapper.class);

      @Before
      public void init() {
      this.candidateService = new CandidateService(candidateRepository,
      candidateMapper, userDetailsService, userMapper);
      }
      @Test
      @WithMockUser(authorities = RolesConstants.ADMIN)
      public void givenUser_whenGetCandidateOrCreateForLogin_create() {
        // Pre-conditions
       ...

        // Mocking data
       ...

        // Given
        given(userRepository.findOneByLogin(eq(login)))
          .willReturn(Optional.of(user));
        given(candidateRepository.findOneByUserLogin(eq(login)))
          .willReturn(Option.of(candidate));

        // When
        CandidateDTO candidateDTO = candidateService.getCandidateOrCreateForLogin(login);

        // Then
       ...
      }

NPE通过此行引发:

candidateDTO.setUser( userMapper.toDto( candidate.getUser() ) );

在CandidateMapperImpl中,因为候选人MapperImpl中的userMapperImpl实例(变量名称userMapper)为空。

当我使用spring-boot:run启动应用程序但仅使用UnitTest启动应用程序时不会发生

任何想法或建议将不胜感激。让我知道您是否需要更多信息或详细信息,或者我错过了重要事项。

谢谢

编辑:

我修复了使用@Autowired并使用此类注释来注释Mapper的问题:

@SpringBootTest(classes = {CandidateMapperImpl.class, UserMapperImpl.class, UserRolesMapperImpl.class,
  CandidateMapper.class, UserMapper.class, UserRolesMapper.class})

概括:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {SubMapperImpl.class, SubMapper.class, 
OtherSubMapper.class, OtherSubMapperImpl.class...})
public class ServiceTest {

@Autowired
Mapper mapper;

...

}

1 个答案:

答案 0 :(得分:0)

基于带有when 'C' then注释的测试(这是为了在测试中添加spring上下文),您似乎真的不想嘲笑嵌套的映射器,对吗?如果您希望使用Spring上下文,只需将其映射器及其所有嵌套的映射器自动布线。参见:https://stackoverflow.com/a/48503708/1098564

下面(使用了Mockito ...对MockBean还不熟悉),将为您提供一个“夹具”(即CandidateService),并注入所有嵌套的映射器(通过@Autowired),其余的依赖项都被模拟掉了。 MockBean可能有一种更干净的方法,但是目前没有时间对其进行全面测试。

cg$rec_its.ite_id              := 63;