JUnit - Как смоделировать вложенный картограф MapStruct - PullRequest
0 голосов
/ 05 ноября 2018

Я получаю раздражающий NPE, когда я запускаю модульный тест для класса уровня обслуживания. Этот класс использует автоматически сгенерированный маппер из MapStruct, который внутри использует другой маппер (см. В аннотации Mapper атрибут «using»):

    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;
  }
}

Мой юнит-тест:

    @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, потому что экземпляр userMapperImpl (имя переменной userMapper) внутриандидатаMapperImpl имеет значение null.

Этого не происходит, когда я запускаю приложение с весенней загрузкой: запускаю, но только с UnitTest

Любые идеи или предложения будут оценены. Дайте мне знать, если вам нужно больше информации или подробностей или я пропустил что-то важное.

Спасибо

EDIT:

Я исправил проблемы с аннотацией Mapper с помощью @Autowired и использовал эту аннотацию класса:

@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 голосов
/ 05 ноября 2018

Кажется, на основании вашего теста, помеченного @RunWith(SpringRunner.class) (который предназначен для добавления пружинного контекста в ваш тест), вы действительно не хотите издеваться над вложенными мапперами, верно? Если вы хотите контекст весны, просто подключите свой маппер со всеми вложенными мапперами. Смотри: https://stackoverflow.com/a/48503708/1098564

Ниже (с mockito ... еще не очень знакомым с MockBean), вы получите «приспособление» (то есть CandidateService) со всеми вложенными вложенными преобразователями (через @Autowired), а остальные зависимости будут смоделированы. Вероятно, с MockBean есть более понятный способ, но в настоящее время нет времени, чтобы все это проверить.

@RunWith(SpringRunner.class)
@SpringBootTest
public class CandidateServiceTest {

    @Autowired
    @InjectMocks
    private CandidateService fixture;

    @Mock
    private UserRepository userRepository;
    @Mock
    private CandidateRepository candidateRepository;
    @Mock
    private UserDetailsService userDetailsService;
    @Autowired
    private CandidateMapper candidateMapper;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
    }
    //....tests
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...