Проверка лямбда-функции с резьбой в пружинном контроллере

У меня есть простая конечная точка в контроллере, как это:

private final ExecutorService threadPoolExecutor = Executors.newFixedThreadPool(6);
@PostMapping(path = "/batch")
public ServiceResponse batch(@RequestBody BatchRequest request) {
    threadPoolExecutor.submit(() -> {
        try {
            service.batch(request);
            log.info("Batch finished");
        } catch (Exception e) {
            log.error("Failed to execute. Cause: ");
            e.printStackTrace();
        }
    });
    return ServiceResponse.asSuccess("Ok");
}

Это было сделано так, потому что запуск службы может занять несколько минут, поэтому мы избегаем блокировки всей системы. Я пытаюсь сделать модульный тест для этого и поймать его исключение (увеличение покрытия кода). Это то, что я придумал до сих пор

@Rule
public ExpectedException exception = ExpectedException.none();

@InjectMocks
private MyController controller;

@MockBean
private MyService service;

@Test
public void testBatchThrowsException() throws Exception {
    createRequest();

    when(service.batch(any())).thenThrow(Exception.class);


    mockMvc.perform(post(Controller.URL_PREFIX+"/batch")
            .contentType(MediaType.APPLICATION_JSON)
            .content(request.toString()))
            .andDo(MockMvcResultHandlers.print())
            .andExpect(status().isOk());
    exception.expect(Exception.class);
}

Но, конечно, он возвращает успех, так как поток все еще идет, когда запрос заканчивается. Есть ли способ высмеять исполнителя и получить результаты или что-то в этом роде? Я пытался использовать Awaitility, но не могу правильно вызвать лямбда-функцию.

1 ответ

Чтобы "вернуть что-то", единственное, что вы можете сделать, - это изменить реализацию кода контроллера (возможно, с использованием Future или чего-то еще).

Однако, если вы не можете сделать это, идея может заключаться в том, чтобы задержать основной поток в тестовом примере, а затем проверить, вызывается ли определенный метод.

Если вы не можете изменить реализацию реального кода, мой совет:

  • ниже вызов контроллера в тестовом классе - задержать основной поток с Thread.sleep или что-то еще
  • бросить макет исключения из службы
  • проверять производственное поведение с помощью mockito: подсчитывать вызовы printStackTrace() при исключении mock, подсчитывать вызовы службы
  • опционально - сделать тайм-аут на тесте, чтобы быть уверенным, что он длится ожидаемый период времени

Кроме того, прочитайте Ожидание всех потоков, порожденных моим тестируемым кодом в тестовом примере JUnit.

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