Mock测试时产生HttpMediaTypeNotSupportedException异常,415状态码问题的解决办法
Mock测试时产生HttpMediaTypeNotSupportedException异常,415状态码问题的解决办法
一. 异常问题
我在项目中利用Mock进行测试时,产生了HttpMediaTypeNotSupportedException异常信息:
Resolved Exception: Type = org.springframework.web.HttpMediaTypeNotSupportedException
并且有如下状态码提示,本来启动200状态码,现在得到了415状态码。
AssertionError: Status expected:<200> but was:<415>
异常信息描述:
MockHttpServletRequest:
HTTP Method = POST
Request URI = /user/save
Parameters = {}
Headers = [Accept:"application/json", Content-Length:"37"]
Body = {"username":"test3","password":"123"}
Session Attrs = {}
Handler:
Type = com.yyg.boot.web.UserController
Method = com.yyg.boot.web.UserController#save(User)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = org.springframework.web.HttpMediaTypeNotSupportedException
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 415
Error message = null
Headers = [Accept:"application/json, application/octet-stream, application/xml, application/*+json, text/plain, text/xml, application/x-www-form-urlencoded, application/*+xml, multipart/form-data, multipart/mixed, */*"]
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
java.lang.AssertionError: Status expected:<200> but was:<415>
Expected :200
Actual :415
@Test
public void save() throws Exception {
String json = "{\"username\":\"test3\",\"password\":\"123\"}";
mvc.perform(MockMvcRequestBuilders.post("/user/save")
.accept(MediaType.APPLICATION_JSON)
//传json参数
.content(json))
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcResultHandlers.print());
}
@Test
public void save() throws Exception {
String json = "{\"username\":\"test3\",\"password\":\"123\"}";
mvc.perform(MockMvcRequestBuilders.post("/user/save")
.accept(MediaType.APPLICATION_JSON)
//添加这样一个设置,保持浏览器请求与接收到的数据类型一致,都是json格式
.contentType(MediaType.APPLICATION_JSON)
//传json参数
.content(json))
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcResultHandlers.print());
}
二. 原因分析
其实从log日志信息中分析可以发现,Mock的请求头中Accept要求的内容类型为”application/json“!
并且415状态码代表的是:服务器无法处理请求附带的媒体格式!也就是对于当前请求的方法和所请求的资源,请求中提交的实体并不是服务器中所支持的格式,因此请求被拒绝!
然后Mock的响应头中返回的Accept数据类型却并不是单纯的”application/json“!
所以产生了415状态码。
我看了一下我的代码,发现是这么写的,原来是只设置了accept请求头接受类型,并没有设置contentType类型。
@Test
public void save() throws Exception {
String json = "{\"username\":\"test3\",\"password\":\"123\"}";
mvc.perform(MockMvcRequestBuilders.post("/user/save")
.accept(MediaType.APPLICATION_JSON)
//传json参数
.content(json))
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcResultHandlers.print());
}
三. 解决办法
在mock中设置accept与contentType类型一致就可以了!
@Test
public void save() throws Exception {
String json = "{\"username\":\"test3\",\"password\":\"123\"}";
mvc.perform(MockMvcRequestBuilders.post("/user/save")
.accept(MediaType.APPLICATION_JSON)
//添加这样一个设置,保持浏览器请求与接收到的数据类型一致,都是json格式
.contentType(MediaType.APPLICATION_JSON)
//传json参数
.content(json))
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcResultHandlers.print());
}
四. Accept与Content-Type的区别
1. Http报头分类
Http报头分为通用报头,请求报头,响应报头和实体报头。
-
请求方的HTTP报头包括:通用报头|请求报头|实体报头
-
响应方的HTTP报头包括:通用报头|响应报头|实体报头
2. 两者类型不同
Accept属于请求报头,Content-Type属于实体报头。
3. 两者作用不同
Accept代表发送端(客户端/浏览器)希望接受的数据类型。 比如:Accept:application/json; 代表客户端/浏览器希望接受的数据类型是json类型。
Content-Type代表发送端(客户端or浏览器or服务器)发送的实体数据的数据类型。比如:Content-Type:application/json; 代表发送端/浏览器/服务器发送的数据格式是json。
二者合起来, Accept:application/json; Content-Type:application/json,即代表希望接受的数据类型是json格式,本次请求发送的数据格式也是json。