我正在Spring RestController中使用集成测试和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("test@mail.com")
.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":"test@mail.com"}
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-Type
在Test.java
中调用mockMvc
时,我使用了正确的Test.java
和Accept
头,但它仍然会给HttpMediaTypeNotSupportedException带来好处。在Accept
和Content-Type
中尝试了许多组合,但仍然无法工作。
我读过很多关于这个例外的问题,但是找不到问题所在。仍然无法弄清楚为什么它说的是HttpMediaTypeNotSupportedException。
Update:按照建议删除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":"test@mail.com"}
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;
}
发布于 2022-07-06 08:19:44
让我们看看你的测试。
@WebMvcTest(classes = Controller.class)
@AutoConfigureMockMvc(addFilters = false)
class ControllerTest {
private ObjectMapper objectMapper;
@MockBean
private Service service;
@Autowired
private MockMvc mockMvc;
@Test
void createOrAdd_shouldReturnErrorResponseOnInvalidInput() throws Exception {
Request request = Request.builder()
.name("name<script>")
.primaryEmail("test@mail.com")
.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());
}
}
首先,@ExtendWith(MockitoExtension.class)
没有添加任何内容,因为您正在正确地使用由Spring处理的@MockBean
注释。所以你应该把它去掉。
接下来,@SpringBootTest
用于引导完整应用程序,以运行集成测试。您想要的是对web的切片测试,所以不要使用@SpringBootTest
使用@WebMvcTest
,这将使您的测试更快。然后,您也可以删除@AutoConfigureMockMvc
,因为这是默认添加的。
您使用@AutoConfigureMockMvc(addFilters = false)
禁用了所有过滤器,这可能是由于您获得了403个。所拥有的403是启用CSRF (默认情况下启用)而不是将其添加到请求中的结果。如果您不需要CSRF (您可能想要它),可以在中禁用它,或者如果您希望它修改您的请求。
查看错误,您的罪魁祸首是将characterEncoding
添加到内容类型,因此您可能希望/应该删除它。
你的测试应该是这样的。
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*;
@WebMvcTest(Controller.class)
class ControllerTest {
private ObjectMapper objectMapper = new ObjectMapper();
@MockBean
private Service service;
@Autowired
private MockMvc mockMvc;
@Test
void createOrAdd_shouldReturnErrorResponseOnInvalidInput() throws Exception {
Request request = Request.builder()
.name("name<script>")
.primaryEmail("test@mail.com")
.build();
mockMvc.perform(MockMvcRequestBuilders.post("/api/create")
.with(csrf()) // Add CSRF field for security
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(objectMapper.writeValueAsString(request))
.andExpect(MockMvcResultMatchers.status().isBadRequest());
}
}
注意:如果您也有身份验证,您可能还需要将用户/密码添加到请求中,作为在此解释
发布于 2022-07-05 20:14:21
我认为您缺少@WebMvcTest(controllers = Controller.class)
https://stackoverflow.com/questions/72874685
复制相似问题