MocMVC给出HttpMessageNotReadableException [英] MocMVC giving HttpMessageNotReadableException

查看:768
本文介绍了MocMVC给出HttpMessageNotReadableException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我仍在学习有关测试的方法,并且正在尝试让MockMvc测试对我有用.这是一个简单的REST控制器,目前仅使用帖子中json的信息进行一些身份验证.我实际上已经实现了代码,所以我知道它是有效的,因为我以json格式获取了正确的响应,正确的输入和错误消息.我的问题是,即使实际代码可行,测试仍会因HttpMessageNotReadableException而失败,因此我假设我没有正确设置测试.你们能提供的任何帮助都会很棒.

I'm still learning my way around testing and I'm trying to get a MockMvc test to work for me. It's a simple REST controller that at this point is only doing some authentication using information from json in the post. I've actually implemented the code, so I know it's working because I get back both the correct response with the correct input and the error messages I've put together, both in a json format. My problem is that the test keeps failing with a HttpMessageNotReadableException, even though the actual code works, so I'm assuming I don't have my test set up right. Any help you guys can give would be great.

这是我的控制器

@Controller
public class RequestPaymentController {
protected final Log logger = LogFactory.getLog(getClass());
private PaymentService paymentService;
private LoginService loginService;

@Autowired
public void setPaymentService(PaymentService paymentService){
    this.paymentService =  paymentService;
}
@Autowired
public void setLoginService(LoginService loginService){
    this.loginService =  loginService;
}

@RequestMapping(value = "/requestpayment", method = RequestMethod.POST, headers="Accept=application/json")
@ResponseBody
public ResponseEntity<PaymentResult> handleRequestPayment(@RequestBody PaymentRequest paymentRequest, HttpServletRequest request, HttpServletResponse response, BindingResult result) throws Exception{
    ResponseEntity<PaymentResult> responseEntity = null;
    new LoginValidator().validate(paymentRequest, result);
    boolean valid = loginService.isLoginValid(paymentRequest, result);
    if (valid){
      responseEntity = setValidResponse(paymentRequest);
    }else {
        throw new TumsException("exception message");

    }
    return responseEntity;
}


private ResponseEntity<PaymentResult> setValidResponse(PaymentRequest paymentRequest){
    PaymentResult paymentResult = paymentService.getResults(paymentRequest);

    return new ResponseEntity<PaymentResult>(paymentResult, HttpStatus.OK);
}


}

这是我的测试代码:

public class RequestPaymentControllerTest {

PaymentService mockPaymentService;
RequestPaymentController requestPaymentController;
HttpServletRequest mockHttpServletRequest;
HttpServletResponse mockHttpServletResponse;
PaymentRequest mockPaymentRequest;
BindingResult mockBindingResult;
LoginService mockLoginService;
PaymentResult mockPaymentResult;
MockMvc mockMvc;


@Before
public void setUp() throws Exception {
    mockPaymentService = createMock(PaymentService.class);
    mockHttpServletRequest = createMock(HttpServletRequest.class);
    mockHttpServletResponse = createMock(HttpServletResponse.class);
    mockPaymentRequest = createMock(PaymentRequest.class);
    requestPaymentController = new RequestPaymentController();
    mockBindingResult = createMock(BindingResult.class);
    mockLoginService = createMock(LoginService.class);
    requestPaymentController.setPaymentService(mockPaymentService);
    mockPaymentResult = createMock(PaymentResult.class);
    mockMvc = MockMvcBuilders.standaloneSetup(new RequestPaymentController()).build();

}

@After
public void tearDown() throws Exception {
    mockPaymentService = null;
    mockHttpServletRequest = null;
    mockHttpServletResponse = null;
    mockPaymentRequest = null;
    requestPaymentController = null;
    mockBindingResult = null;
    mockLoginService = null;
    mockPaymentResult = null;
    mockMvc = null;
}


@Test
public void testHandleRequestPayment() throws Exception{
    initializeStateForHandleRequestPayment();
    createExpectationsForHandleRequestPayment();
    replayAndVerifyExpectationsForHandleRequestPayment();

}



private void initializeStateForHandleRequestPayment(){

}

private void createExpectationsForHandleRequestPayment(){
    mockPaymentRequest.getServiceUsername();
    expectLastCall().andReturn("testuser");
    mockPaymentRequest.getServicePassword();
    expectLastCall().andReturn("password1!");
    mockLoginService.isLoginValid(mockPaymentRequest,mockBindingResult);
    expectLastCall().andReturn(true);
    mockPaymentService.getResults(mockPaymentRequest);
    expectLastCall().andReturn(mockPaymentResult);
}

private void replayAndVerifyExpectationsForHandleRequestPayment() throws Exception{
    replay(mockPaymentService, mockBindingResult, mockHttpServletRequest, mockHttpServletResponse, mockPaymentRequest, mockLoginService);
    requestPaymentController.setLoginService(mockLoginService);
    requestPaymentController.handleRequestPayment(mockPaymentRequest, mockHttpServletRequest, mockHttpServletResponse, mockBindingResult);
    mockMvc.perform(post("/requestpayment")
            .contentType(MediaType.APPLICATION_JSON)
            .accept(MediaType.APPLICATION_JSON))
            .andDo(print())
            .andExpect(status().isBadRequest());
    verify(mockPaymentService, mockBindingResult, mockHttpServletRequest, mockHttpServletResponse, mockPaymentRequest, mockLoginService);

}
}

andDo(print())的结果是:

The results of the andDo(print()) are:

MockHttpServletRequest:
     HTTP Method = POST
     Request URI = /requestpayment
      Parameters = {}
         Headers = {Content-Type=[application/json], Accept=[application/json]}

         Handler:
            Type = portal.echecks.controller.RequestPaymentController
          Method = public org.springframework.http.ResponseEntity<portal.echecks.model.PaymentResult> portal.echecks.controller.RequestPaymentController.handleRequestPayment(portal.echecks.model.PaymentRequest,javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse,org.springframework.validation.BindingResult) throws java.lang.Exception

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

    ModelAndView:
       View name = null
            View = null
           Model = null

        FlashMap:

MockHttpServletResponse:
          Status = 400
   Error message = null
         Headers = {}
    Content type = null
            Body = 
   Forwarded URL = null
  Redirected URL = null
         Cookies = []

Process finished with exit code 0

如您所见,当我期望错误的请求状态时,测试通过了,但是我已经记录了日志,而且我知道我发回的ResponseBody的状态为200.就像我说的那样,这是我第一次使用MockMvc,所以我认为我没有进行正确的设置.有什么建议?

As you can see, the test passes when I'm expecting a bad request status, but I've put in logging and I know that the ResponseBody I'm sending back has a 200 status. Like I said, this is my first time with MockMvc, so I assume I've not set something up right. Any suggestions?

推荐答案

HttpMessageNotReadableException

由HttpMessageConverter实现抛出的read方法 失败.

Thrown by HttpMessageConverter implementations when the read method fails.

您的回复中还会收到一个400错误的请求.所有这些都应该告诉您,您没有发送服务器期望的内容.您的服务器期待什么?

You also get a 400 Bad Request in your response. This should all tell you that you are not sending what your server is expecting. What is your server expecting?

@RequestMapping(value = "/requestpayment", method = RequestMethod.POST, headers="Accept=application/json")
@ResponseBody
public ResponseEntity<PaymentResult> handleRequestPayment(@RequestBody PaymentRequest paymentRequest, HttpServletRequest request, HttpServletResponse response, BindingResult result) throws Exception{

这里最主要的是@RequestBody带注释的参数.因此,您要告诉服务器尝试从HTTP POST请求的主体中反序列化PaymentRequest实例.

The main thing here is the @RequestBody annotated parameter. So you are telling your server to try and deserialize a PaymentRequest instance from the body of the HTTP POST request.

因此,让我们看看您的要求

So let's see the request you are making

mockMvc.perform(post("/requestpayment")
        .contentType(MediaType.APPLICATION_JSON)
        .accept(MediaType.APPLICATION_JSON))
        .andDo(print())
        .andExpect(status().isBadRequest());

我看不到您为请求提供正文.应该有一个

I don't see you providing a body to the request. There should be a content(String) call somewhere in there to set the content of the POST request. This content should be a JSON serialization of a PaymentRequest.

请注意,由于您正在使用StandaloneMockMvcBuilder,因此可能需要自行设置HttpMessageConverter实例. MappingJackson2HttpMessageConverter来序列化和反序列化JSON.

Note that because you are using the StandaloneMockMvcBuilder, you might need to set the HttpMessageConverter instances yourself, ie. a MappingJackson2HttpMessageConverter to serialize and deserialize JSON.

请注意,BindingResult参数应紧随与其相关的参数之后.像这样

Note that the BindingResult parameter should come immediately after the parameter to which it's related. Like so

@RequestMapping(value = "/requestpayment", method = RequestMethod.POST, headers="Accept=application/json")
@ResponseBody
public ResponseEntity<PaymentResult> handleRequestPayment(@Valid @RequestBody PaymentRequest paymentRequest, BindingResult result, HttpServletRequest request, HttpServletResponse response) throws Exception{

别忘了@Valid.

请注意,

requestPaymentController.setLoginService(mockLoginService);
requestPaymentController.handleRequestPayment(mockPaymentRequest, mockHttpServletRequest, mockHttpServletResponse, mockBindingResult);

与您正在执行的MockMvc测试完全无关.

is completely unrelated to the MockMvc test you are doing.

这篇关于MocMVC给出HttpMessageNotReadableException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆