MocMVC给出HttpMessageNotReadableException

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

这是我的控制器

@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())的结果是:

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,所以我认为我没有进行正确的设置。有什么建议么?

回答:

HttpMessageNotReadableException

当read方法失败时,由HttpMessageConverter实现抛出。

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

@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注释的参数。因此,您要告诉服务器尝试PaymentRequest从HTTP

POST请求的主体中反序列化实例。

让我们来看看您的要求

mockMvc.perform(post("/requestpayment")

.contentType(MediaType.APPLICATION_JSON)

.accept(MediaType.APPLICATION_JSON))

.andDo(print())

.andExpect(status().isBadRequest());

我看不到您为请求提供正文。那里应该有一个content(String)电话来设置POST请求的内容。此内容应为的JSON序列化PaymentRequest

请注意,由于使用StandaloneMockMvcBuilder,您可能需要自行设置HttpMessageConverter实例,即。一个MappingJackson2HttpMessageConverter序列化和反序列化JSON。


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

@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您正在执行的测试完全无关。

以上是 MocMVC给出HttpMessageNotReadableException 的全部内容, 来源链接: utcz.com/qa/421630.html

回到顶部