带有SpringBoottest的MockMVC正在抛出Exceptiat
我正在借助集成测试和MOPEMVC在Spring RestController中测试请求验证。
contrantertest.java
@ExtendWith(MockitoExtension.class)
@SpringBootTest(classes = Controller.class)
@AutoConfigureMockMvc(addFilters = false)
class ControllerTest {
private ObjectMapper objectMapper;
@MockBean
private Service service;
@Autowired
private MockMvc mockMvc;
@BeforeEach
void setUp() {
objectMapper = new ObjectMapper();
}
@Test
void createOrAdd_shouldReturnErrorResponseOnInvalidInput() throws Exception {
Request request = Request.builder()
.name("name<script>")
.primaryEmail("[email protected]")
.build();
mockMvc.perform(MockMvcRequestBuilders.post("/api/create")
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(objectMapper.writeValueAsString(request))
.characterEncoding("utf-8"))
.andExpect(MockMvcResultMatchers.status().isBadRequest());
}
}
controller.java:
@Slf4j
@RestController
public class Controller {
private final Service service;
public Controller(Service service) {
this.service = service;
}
@PostMapping(value = "/api/create", consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<GenericResponse<Response>> createOrAdd(@RequestBody @Valid Request request, Errors errors) {
GenericResponse<Response> genericResponse = new GenericResponse<>();
try {
if (errors.hasErrors()) {
throw new RequestParamsException(errors.getAllErrors());
}
Response response = service.createOrAdd(request);
genericResponse.setData(response);
return ResponseEntity.ok().body(genericResponse);
} catch (RequestParamsException ex) {
genericResponse.setErrors(ex.getErrors());
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(genericResponse);
}
}
错误:
WARN 17304 --- [ main] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json;charset=utf-8' not supported]
MockHttpServletRequest:
HTTP Method = POST
Request URI = /api/create
Parameters = {}
Headers = [Content-Type:"application/json;charset=utf-8", Accept:"application/json", Content-Length:"162"]
Body = {"name":"name<script>alert(1)</script>","primary_email_address":"[email protected]"}
Session Attrs = {}
Handler:
Type = com.org.controller.Controller
Method = com.org.controller.Controller#createOrAdd(Request, Errors)
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, multipart/mixed, */*"]
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
java.lang.AssertionError: Status expected:<400> but was:<415>
Expected :400
Actual :415
我使用了正确的content> content-type
和接受
标题在使用test.java
使用mockmvc
中进行呼叫时,但它仍然在提供httpmediatypenotsupportedexception。在中尝试了许多组合
和content-type
,但仍无法正常工作。
我读了很多与此例外有关的问题,但在这里找不到问题。 仍然无法弄清楚为什么要说httpmediatypenotsupportedexception。
更新:删除addfilters = false
,如建议,无法找到处理程序本身。
MockHttpServletRequest:
HTTP Method = POST
Request URI = /api/create
Parameters = {}
Headers = [Content-Type:"application/json;charset=utf-8", Accept:"application/json", Content-Length:"162"]
Body = {"name":"name<script>alert(1)</script>","primary_email_address":"[email protected]"}
Session Attrs = {org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository.CSRF_TOKEN=org.springframework.security.web.csrf.DefaultCsrfToken@7a687d8d}
Handler:
Type = null
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 403
Error message = Forbidden
Headers = [X-Content-Type-Options:"nosniff", X-XSS-Protection:"1; mode=block", Cache-Control:"no-cache, no-store, max-age=0, must-revalidate", Pragma:"no-cache", Expires:"0", X-Frame-Options:"DENY"]
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
java.lang.AssertionError: Status expected:<400> but was:<403>
Expected :400
Actual :403
请求:
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class CreateAgencyRequest {
@NotNull(message = "name can't be null")
@JsonProperty(value = "name")
@Pattern(regexp = REGEX_CONST, message = "name is not valid")
private String name;
@NotNull(message = "primary_email_address can't be null")
@JsonProperty(value = "primary_email_address")
private String primaryEmail;
}
I am testing request validation in Spring RestController with the help of integration testing and MockMvc.
ControllerTest.java
@ExtendWith(MockitoExtension.class)
@SpringBootTest(classes = Controller.class)
@AutoConfigureMockMvc(addFilters = false)
class ControllerTest {
private ObjectMapper objectMapper;
@MockBean
private Service service;
@Autowired
private MockMvc mockMvc;
@BeforeEach
void setUp() {
objectMapper = new ObjectMapper();
}
@Test
void createOrAdd_shouldReturnErrorResponseOnInvalidInput() throws Exception {
Request request = Request.builder()
.name("name<script>")
.primaryEmail("[email protected]")
.build();
mockMvc.perform(MockMvcRequestBuilders.post("/api/create")
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(objectMapper.writeValueAsString(request))
.characterEncoding("utf-8"))
.andExpect(MockMvcResultMatchers.status().isBadRequest());
}
}
Controller.java :
@Slf4j
@RestController
public class Controller {
private final Service service;
public Controller(Service service) {
this.service = service;
}
@PostMapping(value = "/api/create", consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<GenericResponse<Response>> createOrAdd(@RequestBody @Valid Request request, Errors errors) {
GenericResponse<Response> genericResponse = new GenericResponse<>();
try {
if (errors.hasErrors()) {
throw new RequestParamsException(errors.getAllErrors());
}
Response response = service.createOrAdd(request);
genericResponse.setData(response);
return ResponseEntity.ok().body(genericResponse);
} catch (RequestParamsException ex) {
genericResponse.setErrors(ex.getErrors());
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(genericResponse);
}
}
Error :
WARN 17304 --- [ main] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json;charset=utf-8' not supported]
MockHttpServletRequest:
HTTP Method = POST
Request URI = /api/create
Parameters = {}
Headers = [Content-Type:"application/json;charset=utf-8", Accept:"application/json", Content-Length:"162"]
Body = {"name":"name<script>alert(1)</script>","primary_email_address":"[email protected]"}
Session Attrs = {}
Handler:
Type = com.org.controller.Controller
Method = com.org.controller.Controller#createOrAdd(Request, Errors)
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, multipart/mixed, */*"]
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
java.lang.AssertionError: Status expected:<400> but was:<415>
Expected :400
Actual :415
I have used the correct Content-Type
and Accept
Headers while making a call in Test.java
using mockMvc
, but still it's giving HttpMediaTypeNotSupportedException. Tried many combinations in Accept
and Content-Type
but still not working.
I have read many SO questions related to this exception, but couldn't find what's the issue here.
Still not able to figure out why it's saying HttpMediaTypeNotSupportedException.
Update : After removing addFilters = false
as suggested, not able to find the handler itself.
MockHttpServletRequest:
HTTP Method = POST
Request URI = /api/create
Parameters = {}
Headers = [Content-Type:"application/json;charset=utf-8", Accept:"application/json", Content-Length:"162"]
Body = {"name":"name<script>alert(1)</script>","primary_email_address":"[email protected]"}
Session Attrs = {org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository.CSRF_TOKEN=org.springframework.security.web.csrf.DefaultCsrfToken@7a687d8d}
Handler:
Type = null
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 403
Error message = Forbidden
Headers = [X-Content-Type-Options:"nosniff", X-XSS-Protection:"1; mode=block", Cache-Control:"no-cache, no-store, max-age=0, must-revalidate", Pragma:"no-cache", Expires:"0", X-Frame-Options:"DENY"]
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
java.lang.AssertionError: Status expected:<400> but was:<403>
Expected :400
Actual :403
Request :
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class CreateAgencyRequest {
@NotNull(message = "name can't be null")
@JsonProperty(value = "name")
@Pattern(regexp = REGEX_CONST, message = "name is not valid")
private String name;
@NotNull(message = "primary_email_address can't be null")
@JsonProperty(value = "primary_email_address")
private String primaryEmail;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
让我们看一下您的考试。
首先,
@extendwith(mockitoextension.class)
在您使用时不会添加任何内容,@mockbean
由Spring处理的注释。因此,您应该删除它。接下来,
@springboottest
用于引导完整的应用程序运行集成测试。您想要的是对网络的切片测试,因此代替@springboottest
使用@webmvctest
这将使您的测试更快。然后,您还可以删除@AutoconFigureMockMvc
,因为默认情况下添加了。您使用
@AutoconFigureMockMvc(addfilters = false)禁用所有过滤器
可能是由于您获得的403所致。您拥有的403是启用CSRF(默认启用)而不是将其添加到请求中的结果。如果您不希望CSRF(可能需要它)在安全配置中禁用该CSRF,或者是否要它修改请求。查看罪魁祸首的错误是
targeenCoding
被添加到内容类型中,因此您可能想要/应该删除它。有了所有的测试,应该看起来像这样。
注意:如果您还具有身份验证,则可能还需要在请求中添加用户/密码,例如在这里解释
Lets take a look at your test.
First the
@ExtendWith(MockitoExtension.class)
doesn't add anything as you are using, correctly, the@MockBean
annotation which is handled by Spring. So you should remove that.Next the
@SpringBootTest
is for bootstrapping the full application to run an integration test. What you want is a sliced test for the web, so instead of@SpringBootTest
use@WebMvcTest
this will make your test considerably faster. You can then also remove@AutoConfigureMockMvc
as that is added by default.You disabled all filters with
@AutoConfigureMockMvc(addFilters = false)
probably due to the 403 you got. The 403 you have is the result of enabling CSRF (enabled by default) and not adding that to the request. If you don't want CSRF (you probably want it) either disable that in the Security configuration, or if you want it modify your request.Looking at the error you have the culprit is the
characterEncoding
being added to the content type, so you probably want/should remove that.With all that your test should look something like this.
NOTE: If you also have authentication in place you might also need to add a user/password to the request as explained here
添加
消耗
和在您的控制器端点中产生
怎么样?显然,端点不接受您在请求中发送的内容类型:您告诉端点:“嘿,我要发送JSON,我只接受JSON响应回来”。但是端点说:“看,在我接受的东西中,没有JSON,所以请重新考虑!”
因此,相应调整。
所有其他配置,测试,注射都是无关紧要的。很高兴有,但不能解决您的问题。
How about adding
consumes
andproduces
in your controller endpoint? Apparently, endpoint does not accept the content type you send in request:You tell endpoint "hey, I am sending JSON and I only accept JSON response back". But endpoint says "Look, among what I accept, there is no JSON, so please rethink!"
So adjust accordingly.
All other configs, testing, injections are irrelevant. Good to have, but does not solve your problem.
我认为您缺少@webmvctest(控制器= Controller.Class)
I think you are missing @WebMvcTest(controllers = Controller.class)