2015-12-17 27 views
9

Sto implementando long polling as per the Spring blog from some time ago.Come testare il timeout di DeferredResultRisultato

Ecco il mio metodo convertito con la stessa firma di risposta di prima, ma invece di rispondere immediatamente, esso utilizza ora polling lungo:

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; 
} 

In particolare mi piacerebbe tornare la risposta pendingOnTimeout quando la richiesta prende troppo lungo (che ho restituito immediatamente prima), per evitare che i proxy interrompano la richiesta.

Ora penso di averlo fatto funzionare così com'è, ma mi piacerebbe scrivere un messaggio inedito che lo confermi. Tuttavia tutti i miei tentativi di usare MockMvc (tramite webAppContextSetup) non mi forniscono un mezzo per affermare che ottengo un'intestazione accepted. Quando ho per esempio provare quanto segue:

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

ottengo il seguente stacktrace:

java.lang.IllegalStateException: risultato asincrona per il gestore [org.springframework.web.context.request.async pubblico .DeferredResult> nl.bioprodict.blast.api.PollController.poll (java.lang.String)] non è stato impostato durante il timeToWait specificato = 25000 in org.springframework.util.Assert.state (Assert.java:392) all'indirizzo org.springframework.test.web.servlet.DefaultMvcResult.getAsyncResult (DefaultMvcResult.java:143) all'indirizzo org.springframework.test.web.servlet .DefaultMvcResult.getAsyncResult (DefaultMvcResult.java:120) a org.springframework.test.web.servlet.request.MockMvcRequestBuilders.asyncDispatch (MockMvcRequestBuilders.java:235) a nl.bioprodict.blast.docs.PollControllerDocumentation.pollPending (PollControllerDocumentation .java: 53) ...

I test framework Spring relativi a questo che ho potuto trovare tutto l'uso beffardo che sembra: https://github.com/spring-projects/spring-framework/blob/master/spring-web/src/test/java/org/springframework/web/context/request/async/WebAsyncManagerTimeoutTests.java

Come faccio a testare la corretta gestione del DeferredResult timeoutResult?

+0

Per essere chiari: Sembra funzionare bene in test di integrazione, ma mi piacerebbe anche voler testare questo in 'primavera-restdocs-mockmvc'. – Tim

+0

Mi sono appena imbattuto in questo stesso identico problema. Hai mai trovato una soluzione che permetta di testare i timeout su DeferredResults? –

+0

@John no, non ancora, anche se ho smesso di cercare ora .. Fammi sapere se trovi qualcosa! – Tim

risposta

3

Nel mio caso, dopo aver passato il codice sorgente di primavera e aver impostato il timeout (10000 millisecondi) e ottenuto il risultato asincrono, l'ho risolto per me, come;

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

Il mio intero codice di test era;

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()); 

Speranza che aiuta ..

+0

Grazie! Votato come ritengo potrebbe aiutare qualcuno, ma nel mio caso non funziona ancora con '@SpringBootTest()' né '@WebMvcTest (PollController.class)'. Entrambi continuano a vomitare: "Il risultato posticipato non è stato impostato durante il timeToWait = 25000' specificato .. Grazie però! – Tim