0

I have an observable and as it may take a long time i return spring's DeferredResult.

This is the controller logic I'm using:

public DeferredResult<ResponseEntity<InputStreamResource>> getSomeFile() {
    DeferredResult<ResponseEntity<InputStreamResource>> deferredResult = new DeferredResult<>(TIMEOUT);
    Observable<File> observableFile = fileService.getSomeFile();
    observableFile
            .map(this::fileToInputStreamResource)
            .map(resource -> ResponseEntity.ok().cacheControl(CacheControl.maxAge(1, TimeUnit.HOURS).cachePublic()).body(resource))
            .subscribe(deferredResult::setResult, ex -> {
                deferredResult.setErrorResult(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null));
            });
    return deferredResult;
}

And this is my test case:

@Test
public void getSomeFile() throws Exception {
    this.mockMvc.perform(get("/somefile").accept(MediaType.parseMediaType("application/xml;charset=UTF-8")))
            .andExpect(request().asyncStarted())
            .andExpect(status().isOk())
            .andDo(result -> {
                ResponseEntity<InputStreamResource> fileResource = (ResponseEntity<InputStreamResource>) result.getAsyncResult();
                InputStream fileResourceInputStream = fileResource.getBody().getInputStream();
                FooBar foobar = (FooBar) jaxb2Marshaller.unmarshal(new StreamSource(fileResourceInputStream));
                assertThat(foobar.getFoos(), is(not(empty())));
            });
}

This test fails when I instantiate DeferredResult without timeout set as it uses generic timeout that is set for rest template (10 sec). If i explicitly set the timeout new DefferredResult(Long.MAX_VALUE) it fails with same exception:

java.lang.IllegalStateException: Async result for handler [public org.springframework.web.context.request.async.DeferredResult<org.springframework.http.ResponseEntity<org.springframework.core.io.InputStreamResource>> com.example.controller.FileController.getSomeFile()] was not set during the specified timeToWait=9223372036854775807
    at org.springframework.test.web.servlet.DefaultMvcResult.getAsyncResult(DefaultMvcResult.java:145)
    at org.springframework.test.web.servlet.DefaultMvcResult.getAsyncResult(DefaultMvcResult.java:121)
    at org.springframework.test.web.servlet.result.RequestResultMatchers$4.match(RequestResultMatchers.java:114)
    at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:171)

So how timeout should be configured or where's a problem ?

marknorkin
  • 3,904
  • 10
  • 46
  • 82
  • Does the observable produce items? – kjsebastian Oct 25 '16 at 07:08
  • @conscells yes. as i look now the test won't wait the specified timeout and terminates earlier – marknorkin Oct 25 '16 at 07:52
  • answer at https://stackoverflow.com/a/45033122/1290868 may help – myuce Jul 11 '17 at 11:24
  • It seems that it is not end to end test, but just testing the controller so I guess you have a ready file to return. Right? It should not take more than a second. Try to call `result.getRequest().getAsyncContext().complete()` to trigger the `deferredResult::setResult` – elirandav Aug 30 '19 at 12:48

0 Answers0