0

I am using SpringBoot 2.0.6-RELEASE

When I configure my api to use a CompletableFuture with no executor service provided - my tests run successfully. For example this tests passes ok

public Future<List<AlertsBodyVO>> getAlerts(@PathVariable(value = "userId") final String userId) {
        return CompletableFuture.supplyAsync(() -> Service.getAlerts(userId));
    }


    @Test
    public void testGetAlerts_NullResult() throws Exception {
        String userId = "123456";

        List<AlertsBodyVO> alertsVOList = null;     

        Mockito.when(mockService.getAlerts(Mockito.anyString())).thenReturn(alertsVOList);

        MvcResult result = this.mockMvc.perform(get("/alerts/{userId}",  userId)).andExpect(status().isOk())
                .andReturn();

        mockMvc.perform(asyncDispatch(result)).andExpect(status().isOk())
                .andExpect(jsonPath("$").doesNotExist())
                .andReturn();        

        Mockito.verify(mockService, Mockito.times(1)).getAlerts(Mockito.anyString());
    }   

However - when I define my api to use an executorService as follows

public Future<List<AlertsBodyVO>> getAlerts(@PathVariable(value = "userId") final String userId) {
        return CompletableFuture.supplyAsync(() -> Service.getAlerts(userId), executorService);
    }

I get the following error

java.lang.IllegalStateException: Async result for handler [public java.util.concurrent.Future<java.util.List<com.domain.AlertsBodyVO>> com.controllers.API.getAlerts(java.lang.String)] was not set during the specified timeToWait=10000
at org.springframework.test.web.servlet.DefaultMvcResult.getAsyncResult(DefaultMvcResult.java:146)
at org.springframework.test.web.servlet.DefaultMvcResult.getAsyncResult(DefaultMvcResult.java:136)
at org.springframework.test.web.servlet.request.MockMvcRequestBuilders.asyncDispatch(MockMvcRequestBuilders.java:269)
at com.controllers.APITest.testGetAlerts_NullResult(APITest.java:207)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.mockito.internal.runners.DefaultInternalRunner$1.run(DefaultInternalRunner.java:78)
at org.mockito.internal.runners.DefaultInternalRunner.run(DefaultInternalRunner.java:84)
at org.mockito.internal.runners.StrictRunner.run(StrictRunner.java:39)
at org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.java:161)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)

Any idea how I can get my MockMvc tests to pass when I specify the executorService to use?

Damien
  • 4,081
  • 12
  • 75
  • 126

1 Answers1

1

It is difficult to used Mocked ExecuterService, because you should also mock all their behavior, like

Mockito.when(mockedExecuterService.execute...        

And another hidden calls and processes inside of executor service. Instead of that you can just create simple single thread executor for test purpose, i checked and it work correct with real ExecutorService (for example Executors.newSingleThreadExecutor()) and failed ofcouse with mocked. I think you now it how create test context - Spring Test Context

borino
  • 1,720
  • 1
  • 16
  • 24