MockMvc を使用して、非同期の結果で Spring 4.1 コントローラーをテストしようとしています。ここで説明したのと同じパターンに従いました。
ただし、ここで説明するように戻り値ハンドラーを使用しているため、私のテストは異なります。
https://github.com/AndreasKl/spring-boot-mvc-completablefuture
私のテストコードは次のようになります。
public class MyControllerTest {
private MockMvc mockMvc;
private MyService myService;
private MyController myController;
public MappingJackson2HttpMessageConverter createMessageConverter() {
ObjectMapper objectMapper = new ObjectMapper();
List<MediaType> supportedMediaTypes = Arrays.asList(MediaTypes.JSON_V1);
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setObjectMapper(objectMapper);
converter.setSupportedMediaTypes(supportedMediaTypes);
return converter;
}
@Before
public void setup() throws Exception {
MappingJackson2HttpMessageConverter converter = createMessageConverter();
myService = mock(MyService.class);
controller = new MyController(myService);
mockMvc = MockMvcBuilders.standaloneSetup(controller)
.setMessageConverters(converter)
.setCustomReturnValueHandlers(new CompletableFutureReturnValueHandler())
.build();
}
@Test
public void test() throws Exception {
String value = "foo";
CompletableFuture<ExampleData> futureValue =
CompletableFuture.completedFuture(new ExampleData(value));
when(myService.getExample()).thenReturn(futureValue);
MvcResult mvcResult = mockMvc.perform(get("/example"))
.andExpect(status().isOk())
.andExpect(request().asyncStarted())
.andExpect(request().asyncResult(instanceOf(ExampleData.class)))
.andReturn();
mockMvc.perform(asyncDispatch(mvcResult))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaTypes.JSON_V1_VALUE))
.andExpect(jsonPath("$.property", is(value)));
}
}
StandaloneMockMvcBuilder.setCustomReturnValueHandlers() を使用して戻り値ハンドラーを設定しても、呼び出されることはないようです。これにより、結果が Callable または DeferredResult ではないため、request().asyncStarted() のアサーションが失敗します。
ハンドラーを正しく設定していますか、それとも他に何か不足していますか?
==== ソリューション ======
ドキュメントを読み、デバッガーでステップスルーした後、setCustomReturnValueHandlers() がハンドラーをリストの最後に追加するのに対し、spring-boot-mvc-completablefuture の例ではそれを DeferredResult ハンドラーの前に挿入することがわかりました。非スタンドアロン モードを使用すると、これが可能になります。