Meilan
Meilan

Reputation: 484

Why the CompletableFuture takes forever in my unit test?

I'm writing the unit tests for the old method, which uses CompletableFuture.supplyAsync(). The method is not complex, but my unit test keeps running and does not stop when executing the join(). I believe supplyAsync() should return the value very quickly. Is it because I set up the taskExecutor incorrectly? I'm new to Spring and Java, so please advise anything. Thank you.

Code:

  public Response getReponse(Request request) {
    CompletableFuture<String> vip = CompletableFuture.supplyAsync(() -> {
      if(StringUtils.isBlank(request.getAddress())
      ){ return "";}
        Request newRequest = Request.builder().
                userId(request.getUserId()).
                address(request.getZipCode()).
                build();
        Response newResult =  getResult(newRequest);
        return ("12345".equals(newResult.getZipCode()) + "";
    }, taskExecutor);
    final Response result =  getResult(request);
    result.setVIP(zipCode.join());
    return result;
  }

My unit test:

  @Mock
  private ThreadPoolTaskExecutor taskExecutor;

  @Test
  void getReponseTest(){
    SomeService someService = new SomeService(Constants, logService, taskExecutor);
    final SomeService someServiceSpy = Mockito.spy(someService);
    final Request request = TestHelper.buildRequest();
    final Response response = TestTestHelper.buildResponse();

    doReturn(response).when(someServiceSpy).getResult(any(Request.class));

    Response result = taxServiceSpy.getQuotationV2(taxRequest);

    // assertion
    ...
  }

Upvotes: 1

Views: 2521

Answers (2)

Jared Renzullo
Jared Renzullo

Reputation: 144

You are mocking the ThreadPoolTaskExecutor so when it's told to execute the task, it is not doing anything. The CompletableFuture will never be completed, which is why things are hanging. You would need to either use a real ThreadPoolTaskExecutor, or implement the execute() method in the mocked Executor so it calls the run() method on the runnable passed to it. I don't understand what you're actually trying to accomplish in this unit test though. There doesn't seem to be a point to using an Executor at all. Also there is an error in the code since you call join on a variable called zipCode which does not exist, the future is called vip.

Upvotes: 5

Meilan
Meilan

Reputation: 484

Like Jared mentioned, I built an executor, and it worked.

@Spy
private ThreadPoolTaskExecutor spyTaskExecutor = new ThreadPoolTaskExecutor();

spyTaskExecutor.setCorePoolSize(1);
spyTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);
spyTaskExecutor.initialize();

Upvotes: 1

Related Questions