Refactor async result handling in Spring MVC Test
This change removes the use of a CountDownLatch to wait for the asynchronously computed controller method return value. Instead we check in a loop every 200 milliseconds if the result has been set. If the result is not set within the specified amount of time to wait an IllegalStateException is raised. Additional changes: - Use AtomicReference to hold the async result - Remove @Ignore annotations on AsyncTests methods - Remove checks for the presence of Servlet 3 Issue: SPR-11516
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -24,6 +24,7 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.BDDMockito.*;
|
||||
|
||||
/**
|
||||
@@ -37,80 +38,23 @@ public class DefaultMvcResultTests {
|
||||
|
||||
private DefaultMvcResult mvcResult;
|
||||
|
||||
private CountDownLatch countDownLatch;
|
||||
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
ExtendedMockHttpServletRequest request = new ExtendedMockHttpServletRequest();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setAsyncStarted(true);
|
||||
|
||||
this.countDownLatch = mock(CountDownLatch.class);
|
||||
|
||||
this.mvcResult = new DefaultMvcResult(request, null);
|
||||
this.mvcResult.setAsyncResultLatch(this.countDownLatch);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAsyncResultWithTimeout() throws Exception {
|
||||
long timeout = 1234L;
|
||||
given(this.countDownLatch.await(timeout, TimeUnit.MILLISECONDS)).willReturn(true);
|
||||
this.mvcResult.getAsyncResult(timeout);
|
||||
verify(this.countDownLatch).await(timeout, TimeUnit.MILLISECONDS);
|
||||
public void getAsyncResultSuccess() throws Exception {
|
||||
this.mvcResult.setAsyncResult("Foo");
|
||||
assertEquals("Foo", this.mvcResult.getAsyncResult(10 * 1000));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAsyncResultWithTimeoutNegativeOne() throws Exception {
|
||||
given(this.countDownLatch.await(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS)).willReturn(true);
|
||||
this.mvcResult.getAsyncResult(-1);
|
||||
verify(this.countDownLatch).await(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAsyncResultWithoutTimeout() throws Exception {
|
||||
given(this.countDownLatch.await(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS)).willReturn(true);
|
||||
this.mvcResult.getAsyncResult();
|
||||
verify(this.countDownLatch).await(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAsyncResultWithTimeoutZero() throws Exception {
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void getAsyncResultFailure() throws Exception {
|
||||
this.mvcResult.getAsyncResult(0);
|
||||
verifyZeroInteractions(this.countDownLatch);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalStateException.class)
|
||||
public void getAsyncResultAndTimeOut() throws Exception {
|
||||
this.mvcResult.getAsyncResult(-1);
|
||||
verify(this.countDownLatch).await(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
|
||||
private static class ExtendedMockHttpServletRequest extends MockHttpServletRequest {
|
||||
|
||||
private boolean asyncStarted;
|
||||
private AsyncContext asyncContext;
|
||||
|
||||
public ExtendedMockHttpServletRequest() {
|
||||
super();
|
||||
this.asyncContext = mock(AsyncContext.class);
|
||||
given(this.asyncContext.getTimeout()).willReturn(new Long(DEFAULT_TIMEOUT));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAsyncStarted(boolean asyncStarted) {
|
||||
this.asyncStarted = asyncStarted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAsyncStarted() {
|
||||
return this.asyncStarted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncContext getAsyncContext() {
|
||||
return asyncContext;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ public class StubMvcResult implements MvcResult {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAsyncResult(long timeout) {
|
||||
public Object getAsyncResult(long timeToWait) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -59,23 +59,19 @@ public class AsyncTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testCallable() throws Exception {
|
||||
MvcResult mvcResult = this.mockMvc.perform(get("/1").param("callable", "true"))
|
||||
.andDo(print())
|
||||
.andExpect(request().asyncStarted())
|
||||
.andExpect(request().asyncResult(new Person("Joe")))
|
||||
.andReturn();
|
||||
|
||||
this.mockMvc.perform(asyncDispatch(mvcResult))
|
||||
.andDo(print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().string("{\"name\":\"Joe\",\"someDouble\":0.0,\"someBoolean\":false}"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testDeferredResult() throws Exception {
|
||||
MvcResult mvcResult = this.mockMvc.perform(get("/1").param("deferredResult", "true"))
|
||||
.andExpect(request().asyncStarted())
|
||||
@@ -90,7 +86,6 @@ public class AsyncTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testDeferredResultWithSetValue() throws Exception {
|
||||
MvcResult mvcResult = this.mockMvc.perform(get("/1").param("deferredResultWithSetValue", "true"))
|
||||
.andExpect(request().asyncStarted())
|
||||
|
||||
Reference in New Issue
Block a user