Я хочу протестировать этот метод:
@Override
public GenreResponse fetchGenreById(Long genreId) {
return convertGenreToGenreResponse(findGenreEntityByGenreId(genreId));
}
private GenreResponse convertGenreToGenreResponse(Genre genre) {
return modelMapper.map(genre, GenreResponse.class);
}
private Genre findGenreEntityByGenreId(long genreId) {
return genreRepository.findByGenreId(genreId)
.orElseThrow(() -> new ObjectNotFoundException("Genre with " + genreId + " id not found!"));
}
Я написал тест для этого метода, но он не работает, и я не могу понять, почему. Это мой тест:
@ExtendWith(MockitoExtension.class)
class GenreCrudServiceTest {
@Mock
private ModelMapper mockModelMapper;
@Mock
private GenreRepository mockGenreRepository;
private GenreCrudService genreCrudService;
@BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
genreCrudService = new GenreCrudServiceImpl(mockModelMapper, mockGenreRepository);
}
@Test
public void GenreCrudService_FetchGenreById_ReturnsGenreResponse() {
// Arrange
long genreId = 1;
Genre genre = Genre.builder()
.genreId(genreId)
.title("testTitle")
.build();
Mockito.when(mockGenreRepository.findByGenreId(any(Long.class))).thenReturn(Optional.of(genre));
// Act
GenreResponse genreResponse = genreCrudService.fetchGenreById(genreId);
// Assert
Assertions.assertThat(genreResponse).isNotNull();
}
Но мой тест не работает, выдает ошибку:
Expecting actual not to be null
java.lang.AssertionError:
Expecting actual not to be null
Ошибка возникает в этой строке:
Assertions.assertThat(genreResponse).isNotNull();
Я не могу понять, почему я получаю нулевое значение, потому что здесь я определил:
Mockito.when(mockGenreRepository.findByGenreId(any(Long.class))).thenReturn(Optional.of(genre));
что при поиске жанра по id будет возвращен конкретный Жанр, и дальнейший метод должен преобразовать его в GenreResponse
Вам нужно имитировать метод карты ModelMapper
, чтобы он возвращал ненулевой объект, как показано ниже:
Mockito.when(mockModelMapper.map(genre, GenreResponse.class)).thenReturn(new GenreResponse());
Он возвращается null
, потому что ваш modelMapper
является макетом, и вы не установили его поведение.
Итак, сервисный метод fetchGenreById
на самом деле возвращает то, что возвращает modelMapper.map
. И если modelMapper
является макетом, то не имеет значения, возвращает ли mockGenreRepository.findByGenreId
null
или Optional.of(genre)
, если он не генерирует никаких исключений. В итоге вам нужно настроить modelMapper
:
when(mockModelMapper.map(any(), any(GenreResponse.class))).thenReturn(someGenreResponse);
Я согласен, что в таком случае имеет смысл использовать настоящий ModelMapper
И обратите внимание, что такой тест довольно быстро становится бесполезным, если над картографом высмеивают. Это не требует особого тестирования, кроме того, что последний вызов метода возвращает заглушенное значение. Затем вам придется
verify
выполнить вызов и проверить, получил ли он ожидаемые аргументы. Лучше использовать реальный экземплярModelMapper
, который сопоставляет ответ вашей базы данных с объектом ответа. Таким образом, ваши тесты станут намного более надежными.