【问题标题】:mockMvc POST Junit test failing with HttpMessageNotReadableExceptionmockMvc POST Junit 测试失败并出现 HttpMessageNotReadableException
【发布时间】:2014-09-30 14:14:02
【问题描述】:

我正在尝试对我在控制器中创建的发布请求进行 JUNIT 测试。虽然 GET 成功,但 POST 不成功。

public class SampleObject implements Serializable {

    private static final long serialVersionUID = 1L;
    private String name;
    public SampleObject(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
}

示例发布请求

    @RequestMapping(value = "/post", method = RequestMethod.POST, produces="application/json", consumes="application/json")
    @ResponseBody
    public SampleObject postActiveSource(@RequestBody SampleObject inputObject) {
        return inputObject;
    }

这是我的模拟测试。

public class MockMvcHtmlUnitCreateMessageTest {


MockMvc mockMvc;

@InjectMocks
SampleController controller; 

 @Before
  public void setup() {
    MockitoAnnotations.initMocks(this);

    this.mockMvc = standaloneSetup(controller)
            .setMessageConverters(new MappingJackson2HttpMessageConverter()).build();
  }

@Test
public void test() {

    SampleObject so = controller.new SampleObject("abcd");
    ObjectMapper mapper = new ObjectMapper();


    try {
        this.mockMvc.perform(post("/service/sample/post").content(mapper.writeValueAsString(so)).contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)).andDo(print());

    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
 }

}

我得到了这个例外。

Resolved Exception:
          Type = org.springframework.http.converter.HttpMessageNotReadableException

但是,获取请求可以正常工作。这里出了什么问题?任何帮助将不胜感激。

编辑1:

我注意到以下异常。这可能会有所帮助。

nested exception is com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class com..rest.controller.SampleController$SampleObject]: can not instantiate from JSON object (need to add/enable type information?)
 at [Source: org.springframework.mock.web.DelegatingServletInputStream@c792d4; line: 1, column: 2]

编辑2:

基于a suggestion below,我改修改了构造函数,

public SampleObject(@JsonProperty("name") String name) {
            this.name = name;
}

但是,我得到以下异常

Caused by: java.lang.IllegalArgumentException: Argument #0 of constructor [constructor for SampleController$SampleObject, annotations: [null]] has no property name annotation; must have name when multiple-paramater constructor annotated as Creator at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory.findValueInstantia‌​tor(BasicDeserializerFactory.java:287) ~[jackson-databind-2.3.4.jar:2.3.4] 

【问题讨论】:

  • 这是您第二次编辑中的一个非常奇怪的错误,我无法重现它。尝试重新编译。
  • 是的,我的错。它现在可以看到它。它正在工作!但是,我将 SampleObject 作为一个单独的类。它是在 Controller 中定义的。我不确定该错误是否与此有关。
  • 我要删除编辑号吗? 2?它是如何工作的?
  • 不,您可以出于历史原因保留它。如果你在另一个类里面,那是一个内部类。反序列化完全是另一回事。

标签: java spring rest jackson


【解决方案1】:

默认情况下,Jackson 期望您的 POJO 类有一个无参数的构造函数。如果你需要一个参数化的构造函数,你需要注解它的参数。

public SampleObject(@JsonProperty("name") String name) {
    this.name = name;
}

【讨论】:

    【解决方案2】:

    您可能必须在配置文件中配置MessageConverter。如果您使用 Java 配置:

     protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
            ObjectMapper mapper = new ObjectMapper();
            mapper.setSerializationInclusion(Include.NON_NULL);
    
            MappingJackson2HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter();
            jacksonConverter.setObjectMapper(mapper);
    
            converters.add(jacksonConverter);
        }
    

    【讨论】:

    • 我将您的代码放入 setUp 但同样的错误。我添加了另一个我注意到的异常。可能这会带来一些启示?
    • 它必须在配置中。如果你使用Java Configuration,你可以使用代码。
    • 哦,那是什么配置?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-30
    • 1970-01-01
    • 2015-05-28
    • 2021-01-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多