Spring 5.0.0 MockMvc:不支持的媒体类型,即使设置了正确的 MediaType
Spring 5.0.0 MockMvc: Unsupported media type, even with correct MediaType set
我将 JUnit4 与 Spring Web MVC 测试一起使用,并且我已经对控制器进行了测试 class。
控制器处理 POST 对正文内容为 JSON 的“/test”的请求。我已经使用 Postman 手动测试了此方法,并且如预期的那样收到 400 Bad Request 响应,因为 "name" 属性 是空的。
POST /Server/test HTTP/1.1
Host: localhost:8080
Content-Type: application/json
Cache-Control: no-cache
{
"name": ""
}
但是,当我通过测试 class 向我的控制器发送相同的请求时,我收到 415(不支持的媒体类型)错误,即使请求是相同的。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@WebAppConfiguration
public class MyControllerTest {
@Configuration
public static class MyControllerTestConfiguration {
@Bean
public MyController myController() {
return new MyController();
}
}
private MockMvc mockMvc;
@Before
public void setup() {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
@Test
public void shouldReturnBadRequest_IfBodyIsEmpty() throws Exception {
// Works fine
mockMvc.perform(post("/test"))
.andExpect(status().isBadRequest());
}
@Test
public void shouldReturnBadRequest_IfInvalidFields() throws Exception {
MyDTO dto = new MyDTO();
dto.setName("");
// Jackson object mapper
ObjectMapper mapper = new ObjectMapper();
// TEST FAIL: Gets 415 error
mockMvc.perform(
post("/test")
.content(mapper.writeValueAsString(dto))
.characterEncoding("UTF-8")
.contentType(MediaType.APPLICATION_JSON)
)
.andDo(print())
.andExpect(status().isBadRequest());
}
}
这是 MyController。
@RestController
@EnableWebMvc
public class MyController {
@RequestMapping(value = "/test", method = RequestMethod.POST)
public void init(@javax.validation.Valid @RequestBody MyDTO dto) {
}
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public void validationError(MethodArgumentNotValidException ex) {
}
}
这是 MyDTO。
@lombok.Data
public class MyDTO {
private String name;
}
我的依赖项中也有 Jackson。
下面是测试 class 的请求打印到控制台时的样子:
MockHttpServletRequest:
HTTP Method = POST
Request URI = /test
Parameters = {}
Headers = {Content-Type=[application/json;charset=UTF-8]}
Body = {"name":""}
Session Attrs = {}
Handler:
Type = controller.MyController
Method = public void controller.MyController.init(dto.MyDTO)
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/octet-stream, text/plain, application/xml, text/xml, application/x-www-form-urlencoded, application/*+xml, multipart/form-data, */*]}
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
无论如何,为什么我会收到此错误?这个请求对我来说看起来非常好。任何帮助表示赞赏。谢谢。
我通过使用 @EnableWebMvc 注释我的 MyControllerTestConfiguration 内部静态 class 解决了这个问题。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@WebAppConfiguration
public class MyControllerTest {
@Configuration
@EnableWebMvc // <------------ added this
public static class MyControllerTestConfiguration {
@Bean
public SetupController setupController() {
return new MyController();
}
}
在我的特殊情况下,我有一个 @SpringBootTest
注释 class,并将 @EnableWebMvc
添加到主控制器(具体为 @RestController
)或配置是不可能的。我尝试了不同的方法并且 none 起作用了,可能是因为我们有一些依赖项覆盖了 POM 上的某些 Spring 版本,并且改变它也是不可能的。根据鸭子精灵的回答,我想出了一个具体的测试配置 class:
@TestConfiguration
@EnableWebMvc
public class ControllerTestConfig {
@Bean
public SetupController setupController(SetupService setupService) {
return new SetupController(setupService);
}
}
控制器测试 class 是这样的(大约):
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
@AutoconfigureMockMvc
@Import({SecurityConfig.class, ControllerTestConfig.class})
public class ControllerTests {
@Autowired
private MockMvc mockMvc;
//...
}
我将 JUnit4 与 Spring Web MVC 测试一起使用,并且我已经对控制器进行了测试 class。
控制器处理 POST 对正文内容为 JSON 的“/test”的请求。我已经使用 Postman 手动测试了此方法,并且如预期的那样收到 400 Bad Request 响应,因为 "name" 属性 是空的。
POST /Server/test HTTP/1.1
Host: localhost:8080
Content-Type: application/json
Cache-Control: no-cache
{
"name": ""
}
但是,当我通过测试 class 向我的控制器发送相同的请求时,我收到 415(不支持的媒体类型)错误,即使请求是相同的。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@WebAppConfiguration
public class MyControllerTest {
@Configuration
public static class MyControllerTestConfiguration {
@Bean
public MyController myController() {
return new MyController();
}
}
private MockMvc mockMvc;
@Before
public void setup() {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
@Test
public void shouldReturnBadRequest_IfBodyIsEmpty() throws Exception {
// Works fine
mockMvc.perform(post("/test"))
.andExpect(status().isBadRequest());
}
@Test
public void shouldReturnBadRequest_IfInvalidFields() throws Exception {
MyDTO dto = new MyDTO();
dto.setName("");
// Jackson object mapper
ObjectMapper mapper = new ObjectMapper();
// TEST FAIL: Gets 415 error
mockMvc.perform(
post("/test")
.content(mapper.writeValueAsString(dto))
.characterEncoding("UTF-8")
.contentType(MediaType.APPLICATION_JSON)
)
.andDo(print())
.andExpect(status().isBadRequest());
}
}
这是 MyController。
@RestController
@EnableWebMvc
public class MyController {
@RequestMapping(value = "/test", method = RequestMethod.POST)
public void init(@javax.validation.Valid @RequestBody MyDTO dto) {
}
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public void validationError(MethodArgumentNotValidException ex) {
}
}
这是 MyDTO。
@lombok.Data
public class MyDTO {
private String name;
}
我的依赖项中也有 Jackson。
下面是测试 class 的请求打印到控制台时的样子:
MockHttpServletRequest:
HTTP Method = POST
Request URI = /test
Parameters = {}
Headers = {Content-Type=[application/json;charset=UTF-8]}
Body = {"name":""}
Session Attrs = {}
Handler:
Type = controller.MyController
Method = public void controller.MyController.init(dto.MyDTO)
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/octet-stream, text/plain, application/xml, text/xml, application/x-www-form-urlencoded, application/*+xml, multipart/form-data, */*]}
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
无论如何,为什么我会收到此错误?这个请求对我来说看起来非常好。任何帮助表示赞赏。谢谢。
我通过使用 @EnableWebMvc 注释我的 MyControllerTestConfiguration 内部静态 class 解决了这个问题。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@WebAppConfiguration
public class MyControllerTest {
@Configuration
@EnableWebMvc // <------------ added this
public static class MyControllerTestConfiguration {
@Bean
public SetupController setupController() {
return new MyController();
}
}
在我的特殊情况下,我有一个 @SpringBootTest
注释 class,并将 @EnableWebMvc
添加到主控制器(具体为 @RestController
)或配置是不可能的。我尝试了不同的方法并且 none 起作用了,可能是因为我们有一些依赖项覆盖了 POM 上的某些 Spring 版本,并且改变它也是不可能的。根据鸭子精灵的回答,我想出了一个具体的测试配置 class:
@TestConfiguration
@EnableWebMvc
public class ControllerTestConfig {
@Bean
public SetupController setupController(SetupService setupService) {
return new SetupController(setupService);
}
}
控制器测试 class 是这样的(大约):
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
@AutoconfigureMockMvc
@Import({SecurityConfig.class, ControllerTestConfig.class})
public class ControllerTests {
@Autowired
private MockMvc mockMvc;
//...
}