Тестирование Тест интеграции загрузки RepositorSpring — макет возвращает null

#java #spring-boot #integration-testing #spring-boot-test

#java #spring-boot #интеграция-тестирование #spring-boot-test

Вопрос:

У меня возникли проблемы с интеграционным тестированием моего приложения SpringBoot.

Это базовая структура моего тестируемого класса:

 @Controller
@RequiredArgsConstructor
public class PushNotificationController {
    private final PushNotificationService pnSvc;
    private final PushNotificationRepository pnRepo;
    private final DeviceTokenRepository dtRepo;

/**
 * This method sends all PushNotifications from memory,
 * which are not sent yet.
 */
public List<MiddlemanResponse> send() {
    List<MiddlemanResponse> middlemanResponses = pnSvc.sendAll(dtRepo.findBySendStatus(DeviceTokenEntity.Status.SCHEDULED));

    return middlemanResponses;
}

}
  

Как вы можете видеть, это зависит от двух репозиториев, которые являются интерфейсами, расширяющимися от JpaRepository и Service-class. Все они вводятся через lombok RequiredAllArgs-constructor.

Внутри моего теста я общаюсь с базой данных H2, которая работает нормально, а также я хочу издеваться pnSvc .

Вот мой тестовый класс:

 @RunWith(SpringRunner.class)
@SpringBootTest
public class PushNotificationControllerIntegrationTest {
@Autowired
private PushNotificationController underTest;

@Autowired
private DeviceTokenRepository dtRepo;
@Autowired
private PushNotificationRepository pnRepo;
@MockBean //we mock this dependency because we dont want to send actual notifications
private PushNotificationService pnSvc;

//testvalues
private final Long FIRST_PUSH_NOTIFICATION_ID = 1L;
private final Long FIRST_DEVICE_TOKEN_ID = 1L;
PushNotificationEntity pushNotification = new PushNotificationEntity(FIRST_PUSH_NOTIFICATION_ID, "message", "customString", 1L, "metadata");
DeviceTokenEntity deviceToken = new DeviceTokenEntity(FIRST_DEVICE_TOKEN_ID, "deviceToken",  pushNotification, DeviceTokenEntity.Platform.IPHONE, "applicationType","brandId", DeviceTokenEntity.Status.SCHEDULED);

@Before
public void setUp() throws MiddlemanException {
    when(pnSvc.sendAll(dtRepo.findBySendStatus(DeviceTokenEntity.Status.SCHEDULED))).thenReturn(List.of(new MiddlemanResponse(deviceToken, "response_message")));

    pnRepo.save(pushNotification);
    dtRepo.save(deviceToken);
}

@Test
public void sendOneSuccessTest() {
    List<MiddlemanResponse> responses = underTest.send();

    assertEquals(1, responses.size());
}

}
  

К сожалению, издевательский метод pnSvc.sendAll(...) возвращает null , поэтому список MiddlemanResponse пуст, и мой тест завершается неудачей с:

 org.opentest4j.AssertionFailedError: expected: <1> but was: <0>
Expected :1
Actual   :0
  

Я ожидаю, что издевательский метод должен вернуть установленное значение List.of(new MiddlemanResponse(deviceToken, "response_message") .

РЕШЕНИЕ Благодаря dbl и Джанлуке Муса за ваши ответы я пошел с подходом Джанлуки Мусы использовать any() вместо передачи фактического параметра -> pnSvc.sendAll(any()) при издевательстве над ответом

Также я не использовал предложенный Джанлукой Мусой, org.mockito.Matchers.any а org.mockito.Mockito.any скорее из-за его устаревания.

Комментарии:

1. Макет возвращает null значение по умолчанию, если вы не укажете конкретное значение, которое будет возвращено…

2. В случаях when(that.doThis(someVal).thenReturn(blah) вам следует использовать сопоставитель… Нравится when(that.doThis(eq(someVal)).thenReturn(blah)

Ответ №1:

Вероятно, ошибка в том, что фильтр для макета неверен, вы можете использовать универсальный селектор для имитации sendAll (), попробуйте это

 when(pnSvc.sendAll(org.mockito.Mockito.any()).thenReturn(List.of(new MiddlemanResponse(deviceToken, "response_message")));
  

Комментарии:

1. any тоже вариант, но он может быть еще более конкретным в зависимости от требований теста.

2. это сработало, но я использовал org.mockito. Для этого тестового случая достаточно Mockito.any вместо устаревшего предлагаемого @dbl any