2015-12-17 9 views
9

Wdrażam long polling as per the Spring blog from some time ago.Jak przetestować czas Time DeferredResultResult

Oto moja przerobiona metoda z samym podpisu odpowiedzi jak poprzednio, ale zamiast reagować natychmiast, że teraz wykorzystuje długie odpytywanie:

private Map<String, DeferredResult<ResponseEntity<?>>> requests = new ConcurrentHashMap<>(); 

@RequestMapping(value = "/{uuid}", method = RequestMethod.GET) 
public DeferredResult<ResponseEntity<?>> poll(@PathVariable("uuid") final String uuid) { 
    // Create & store a new instance 
    ResponseEntity<?> pendingOnTimeout = ResponseEntity.accepted().build(); 
    DeferredResult<ResponseEntity<?>> deferredResult = new DeferredResult<>(TWENTYFIVE_SECONDS, pendingOnTimeout); 
    requests.put(uuid, deferredResult); 

    // Clean up poll requests when done 
    deferredResult.onCompletion(() -> { 
     requests.remove(deferredResult); 
    }); 

    // Set result if already available 
    Task task = taskHolder.retrieve(uuid); 
    if (task == null) 
     deferredResult.setResult(ResponseEntity.status(HttpStatus.GONE).build()); 
    else 
     // Done (or canceled): Redirect to retrieve file contents 
     if (task.getFutureFile().isDone()) 
      deferredResult.setResult(ResponseEntity.created(RetrieveController.uri(uuid)).build()); 

    // Return result 
    return deferredResult; 
} 

W szczególności chciałbym zwrócić odpowiedź pendingOnTimeout gdy żądanie trwa zbyt długi (który wróciłem bezpośrednio przed), aby zapobiec odcięciu żądania od serwerów proxy.

Teraz myślę, że udało mi się to jak jest, ale chciałbym napisać unittest, który to potwierdza. Jednak wszystkie moje próby użycia MockMvc (przez webAppContextSetup) nie zapewniają mi sposobu potwierdzenia, że ​​otrzymałem nagłówek accepted. Kiedy na przykład spróbować wykonać następujące czynności:

@Test 
public void pollPending() throws Exception { 
    MvcResult result = mockMvc.perform(get("/poll/{uuid}", uuidPending)).andReturn(); 
    mockMvc.perform(asyncDispatch(result)) 
      .andExpect(status().isAccepted()); 
} 

otrzymuję następujący StackTrace:

java.lang.IllegalStateException: wynik asynchroniczny dla obsługi [org.springframework.web.context.request.async publicznego .DeferredResult> nl.bioprodict.blast.api.PollController.poll (java.lang.String)] nie został ustawiony w określonym czasieToWait = 25000 w org.springframework.util.Assert.state (Assert.java:392) at org.springframework.test.web.servlet.DefaultMvcResult.getAsyncResult (DefaultMvcResult.java:143) at org.springframework.test.web.servlet .DefaultMvcResult.getAsyncResult (DefaultMvcResult.java:120) w org.springframework.test.web.servlet.request.MockMvcRequestBuilders.asyncDispatch (MockMvcRequestBuilders.java:235) w nl.bioprodict.blast.docs.PollControllerDocumentation.pollPending (PollControllerDocumentation .java: 53) ...

testów Spring Framework związane z tym, że mogę znaleźć wszystkie korzystania szyderczy wydaje: https://github.com/spring-projects/spring-framework/blob/master/spring-web/src/test/java/org/springframework/web/context/request/async/WebAsyncManagerTimeoutTests.java

Jak mogę przetestować prawidłową obsługę DeferredResult timeoutResult?

+0

Żeby było jasne: To wydaje się działać dobrze w testach integracyjnych, ale też bym chciał to sprawdzić w 'wiosenne restdocs-mockmvc'. – Tim

+0

Właśnie napotkałem ten sam problem. Czy kiedykolwiek znalazłeś rozwiązanie, które pozwala testować limity czasu na DeferredResults? –

+0

@John nope, jeszcze nie, chociaż przestałem szukać teraz. Daj mi znać, jeśli coś znajdziesz! – Tim

Odpowiedz

3

W moim przypadku, po przejściu przez źródłowy kod źródłowy i ustawieniu limitu czasu (10000 milisekund) i uzyskaniu wyniku asynchronicznego, rozwiązałem go dla mnie, jako;

mvcResult.getRequest().getAsyncContext().setTimeout(10000); 
mvcResult.getAsyncResult(); 

Cały mój kod testowy był;

MvcResult mvcResult = this.mockMvc.perform(
           post("<SOME_RELATIVE_URL>") 
           .contentType(MediaType.APPLICATION_JSON) 
           .content(<JSON_DATA>)) 
         ***.andExpect(request().asyncStarted())*** 
          .andReturn(); 

***mvcResult.getRequest().getAsyncContext().setTimeout(10000);*** 
***mvcResult.getAsyncResult();*** 

this.mockMvc 
    .perform(asyncDispatch(mvcResult)) 
    .andDo(print()) 
    .andExpect(status().isOk()); 

Nadzieja to pomaga ..

+0

Dzięki! Uznano, że może pomóc komuś, ale w moim przypadku nie działa jeszcze z '@SpringBootTest()' ani '@WebMvcTest (PollController.class)'. Oba wciąż wyrzucają: 'Odroczony wynik nie został ustawiony w określonym czasieToWait = 25000' .. Mimo to! – Tim