在弹簧控制器中测试螺纹Lambda功能

时间:2018-06-19 15:04:47

标签: multithreading spring-boot junit mockito

我在控制器中有一个简单的端点,因为它是

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,但无法正确调用lambda函数。

1 个答案:

答案 0 :(得分:0)

为了“返回某些东西”,您唯一可以做的就是更改控制器代码的实现(可能是使用Future或其他方式)。

但是,如果您不能执行此操作,则可能是在测试用例中延迟主线程,然后检查是否调用了特定方法。

如果您不能更改实际代码的实现,我的建议是:

  • 在测试类中对控制器的调用下面-使用Thread.sleep或其他方法延迟主线程
  • 从服务中抛出嘲笑异常
  • 使用Mockito验证生产行为:对异常模拟上的printStackTrace()调用进行计数,对服务上的调用进行计数
  • (可选)-进行测试超时,以确保其持续预期的时间段

此外,请阅读Waiting for all threads spawned by my code under test in JUnit test case