@Test
  public void resolveArgumentTypeVariableWithNonGenericConverter() throws Exception {
    Method method = MyParameterizedController.class.getMethod("handleDto", Identifiable.class);
    HandlerMethod handlerMethod = new HandlerMethod(new MySimpleParameterizedController(), method);
    MethodParameter methodParam = handlerMethod.getMethodParameters()[0];

    String content = "{\"name\" : \"Jad\"}";
    this.servletRequest.setContent(content.getBytes("UTF-8"));
    this.servletRequest.setContentType(MediaType.APPLICATION_JSON_VALUE);

    List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
    HttpMessageConverter target = new MappingJackson2HttpMessageConverter();
    HttpMessageConverter proxy =
        ProxyFactory.getProxy(HttpMessageConverter.class, new SingletonTargetSource(target));
    converters.add(proxy);
    RequestResponseBodyMethodProcessor processor =
        new RequestResponseBodyMethodProcessor(converters);

    SimpleBean result =
        (SimpleBean)
            processor.resolveArgument(methodParam, mavContainer, webRequest, binderFactory);

    assertNotNull(result);
    assertEquals("Jad", result.getName());
  }
 @Test(expected = HttpMessageNotReadableException.class)
 public void resolveArgumentRequiredNoContent() throws Exception {
   this.servletRequest.setContent(new byte[0]);
   this.servletRequest.setContentType("text/plain");
   List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
   converters.add(new StringHttpMessageConverter());
   RequestResponseBodyMethodProcessor processor =
       new RequestResponseBodyMethodProcessor(converters);
   processor.resolveArgument(paramString, mavContainer, webRequest, binderFactory);
 }
  @Test
  public void handleReturnValueString() throws Exception {
    List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
    converters.add(new ByteArrayHttpMessageConverter());
    converters.add(new StringHttpMessageConverter());

    RequestResponseBodyMethodProcessor processor =
        new RequestResponseBodyMethodProcessor(converters);
    processor.handleReturnValue("Foo", returnTypeString, mavContainer, webRequest);

    assertEquals("text/plain;charset=ISO-8859-1", servletResponse.getHeader("Content-Type"));
    assertEquals("Foo", servletResponse.getContentAsString());
  }
  @Test
  public void supportsReturnTypeRestController() throws Exception {
    Method method = TestRestController.class.getMethod("handle");
    MethodParameter returnType = new MethodParameter(method, -1);

    List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
    converters.add(new StringHttpMessageConverter());

    RequestResponseBodyMethodProcessor processor =
        new RequestResponseBodyMethodProcessor(converters);

    assertTrue(
        "Failed to recognize type-level @RestController", processor.supportsReturnType(returnType));
  }
  @Test
  public void handleReturnValueStringAcceptCharset() throws Exception {
    this.servletRequest.addHeader("Accept", "text/plain;charset=UTF-8");

    List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
    converters.add(new ByteArrayHttpMessageConverter());
    converters.add(new StringHttpMessageConverter());
    RequestResponseBodyMethodProcessor processor =
        new RequestResponseBodyMethodProcessor(converters);

    processor.writeWithMessageConverters("Foo", returnTypeString, webRequest);

    assertEquals("text/plain;charset=UTF-8", servletResponse.getHeader("Content-Type"));
  }
  @Test
  public void resolveArgumentClassString() throws Exception {
    String content = "foobarbaz";
    this.servletRequest.setContent(content.getBytes("UTF-8"));
    this.servletRequest.setContentType("application/json");

    List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
    converters.add(new StringHttpMessageConverter());
    RequestResponseBodyMethodProcessor processor =
        new RequestResponseBodyMethodProcessor(converters);

    String result =
        (String) processor.resolveArgument(paramString, mavContainer, webRequest, binderFactory);

    assertNotNull(result);
    assertEquals("foobarbaz", result);
  }
  @Test
  public void resolveArgumentClassJson() throws Exception {
    String content = "{\"name\" : \"Jad\"}";
    this.servletRequest.setContent(content.getBytes("UTF-8"));
    this.servletRequest.setContentType("application/json");

    List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
    converters.add(new MappingJackson2HttpMessageConverter());
    RequestResponseBodyMethodProcessor processor =
        new RequestResponseBodyMethodProcessor(converters);

    SimpleBean result =
        (SimpleBean)
            processor.resolveArgument(paramSimpleBean, mavContainer, webRequest, binderFactory);

    assertNotNull(result);
    assertEquals("Jad", result.getName());
  }
  @Test
  public void resolveArgumentRawTypeFromParameterizedType() throws Exception {
    String content = "fruit=apple&vegetable=kale";
    this.servletRequest.setContent(content.getBytes("UTF-8"));
    this.servletRequest.setContentType(MediaType.APPLICATION_FORM_URLENCODED_VALUE);

    List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
    converters.add(new AllEncompassingFormHttpMessageConverter());
    RequestResponseBodyMethodProcessor processor =
        new RequestResponseBodyMethodProcessor(converters);

    @SuppressWarnings("unchecked")
    MultiValueMap<String, String> result =
        (MultiValueMap<String, String>)
            processor.resolveArgument(paramMultiValueMap, mavContainer, webRequest, binderFactory);

    assertNotNull(result);
    assertEquals("apple", result.getFirst("fruit"));
    assertEquals("kale", result.getFirst("vegetable"));
  }
  @Test
  public void resolveArgumentParameterizedType() throws Exception {
    String content = "[{\"name\" : \"Jad\"}, {\"name\" : \"Robert\"}]";
    this.servletRequest.setContent(content.getBytes("UTF-8"));
    this.servletRequest.setContentType(MediaType.APPLICATION_JSON_VALUE);

    List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
    converters.add(new MappingJackson2HttpMessageConverter());
    RequestResponseBodyMethodProcessor processor =
        new RequestResponseBodyMethodProcessor(converters);

    @SuppressWarnings("unchecked")
    List<SimpleBean> result =
        (List<SimpleBean>)
            processor.resolveArgument(paramGenericList, mavContainer, webRequest, binderFactory);

    assertNotNull(result);
    assertEquals("Jad", result.get(0).getName());
    assertEquals("Robert", result.get(1).getName());
  }
  @Test
  public void jacksonJsonViewWithResponseBody() throws Exception {
    Method method = JacksonViewController.class.getMethod("handleResponseBody");
    HandlerMethod handlerMethod = new HandlerMethod(new JacksonViewController(), method);
    MethodParameter methodReturnType = handlerMethod.getReturnType();

    List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
    converters.add(new MappingJackson2HttpMessageConverter());

    RequestResponseBodyMethodProcessor processor =
        new RequestResponseBodyMethodProcessor(
            converters, null, Arrays.asList(new JsonViewResponseBodyAdvice()));

    Object returnValue = new JacksonViewController().handleResponseBody();
    processor.handleReturnValue(returnValue, methodReturnType, this.mavContainer, this.webRequest);

    String content = this.servletResponse.getContentAsString();
    assertFalse(content.contains("\"withView1\":\"with\""));
    assertTrue(content.contains("\"withView2\":\"with\""));
    assertTrue(content.contains("\"withoutView\":\"without\""));
  }