Невозможно протестировать метод в сервисной логике

Я хочу протестировать этот метод:

@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

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
65
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вам нужно имитировать метод карты ModelMapper, чтобы он возвращал ненулевой объект, как показано ниже:

Mockito.when(mockModelMapper.map(genre, GenreResponse.class)).thenReturn(new GenreResponse());
Ответ принят как подходящий

Он возвращается null, потому что ваш modelMapper является макетом, и вы не установили его поведение. Итак, сервисный метод fetchGenreById на самом деле возвращает то, что возвращает modelMapper.map. И если modelMapper является макетом, то не имеет значения, возвращает ли mockGenreRepository.findByGenreIdnull или Optional.of(genre), если он не генерирует никаких исключений. В итоге вам нужно настроить modelMapper:

when(mockModelMapper.map(any(), any(GenreResponse.class))).thenReturn(someGenreResponse);

И обратите внимание, что такой тест довольно быстро становится бесполезным, если над картографом высмеивают. Это не требует особого тестирования, кроме того, что последний вызов метода возвращает заглушенное значение. Затем вам придется verify выполнить вызов и проверить, получил ли он ожидаемые аргументы. Лучше использовать реальный экземпляр ModelMapper, который сопоставляет ответ вашей базы данных с объектом ответа. Таким образом, ваши тесты станут намного более надежными.

knittl 29.04.2024 09:51

Я согласен, что в таком случае имеет смысл использовать настоящий ModelMapper

Georgii Lvov 29.04.2024 10:56

Другие вопросы по теме