@RequestParam javax 验证 junit REST 控制器测试
@RequestParam javax validation junit REST controller testing
有没有办法在@RequestParams 上对 javax 验证进行 spring 控制器单元测试。
我在控制器中有一个 get 方法,它使用 @Size 验证请求参数的大小。
@RequestMapping(value = "/getData", method = RequestMethod.GET)
public ResultgetData(
@Size(min=2, max=3)
@RequestParam String number)
有没有办法模拟 junit 测试大小验证器?我想验证大小为 <2 或 > 3 时返回的错误。
样本测试:
@RunWith(MockitoJUnitRunner.class)
public class MyControllerTest {
private MockMvc mockMvc;
@InjectMocks
private MyController myControllerMock;
@Before
public void initTest() {
mockMvc = MockMvcBuilders.standaloneSetup(customerInsuranceControllerMock).setControllerAdvice(exceptionHandler).build();
}
@Test
public void getEmptyData() throws Exception{
mockMvc.perform(MockMvcRequestBuilders.get(
"/getData?number={number}"
, "")
.andExpect(MockMvcResultMatchers.status().isBadRequest()); // This is failing. It returns a success as javax @Size is not triggered.When a empty string is passed , it should be bad request
}
我也试过 spring 跑步者,但似乎还是失败了。
谢谢
如果我对您的问题的理解正确,您可以将 @RunWith
with SpringRunner
and @WebMvcTest
与您的控制器和异常处理程序一起使用 类。
由于您的问题没有显示您的控制器的外观,让我们考虑以下控制器,returns 给定名称的问候语:
@Data
public class Greeting {
private String content;
}
@Validated
@RestController
public class GreetingController {
@GetMapping(path = "/greeting", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Greeting> getGreeting(
@RequestParam @Size(min = 2, max = 10) String name) {
Greeting greeting = new Greeting();
greeting.setContent("Hello " + name + "!");
return ResponseEntity.ok(greeting);
}
}
现在让我们考虑 ConstraintViolationException
的异常处理程序,当某些验证失败时将抛出该异常处理程序:
@Data
public class ApiError {
private String message;
private HttpStatus status;
private Object details;
}
@Data
public class InvalidValue {
private String name;
private Object value;
private String message;
}
@ControllerAdvice
public class WebApiExceptionHandler {
@ExceptionHandler({ConstraintViolationException.class})
public ResponseEntity<Object> handleConstraintViolation(ConstraintViolationException ex,
WebRequest request) {
List<InvalidValue> invalidValues = ex.getConstraintViolations()
.stream()
.map(this::toInvalidValue)
.collect(toList());
ApiError apiError = new ApiError();
apiError.setMessage("Validation error");
apiError.setStatus(HttpStatus.BAD_REQUEST);
apiError.setDetails(invalidValues);
return new ResponseEntity<>(apiError, new HttpHeaders(), apiError.getStatus());
}
private InvalidValue toInvalidValue(ConstraintViolation violation) {
InvalidValue invalidValue = new InvalidValue();
invalidValue.setName(violation.getPropertyPath().toString());
invalidValue.setValue(violation.getInvalidValue());
invalidValue.setMessage(violation.getMessage());
return invalidValue;
}
}
有了这个,您可以编写如下所示的测试和期望:
@RunWith(SpringRunner.class)
@WebMvcTest({GreetingController.class, WebApiExceptionHandler.class})
public class GreetingControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
@SneakyThrows
public void getGreeting_shouldReturn200_whenNameIsValid() {
mockMvc.perform(
get("/greeting")
.param("name", "foo")
.accept(MediaType.APPLICATION_JSON))
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.*", hasSize(1)))
.andExpect(jsonPath("$.content").value("Hello foo!"));
}
@Test
@SneakyThrows
public void getGreeting_shouldReturn400_whenNameIsInvalid() {
mockMvc.perform(get("/greeting").param("name", "_"))
.andDo(print())
.andExpect(status().isBadRequest())
.andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.*", hasSize(3)))
.andExpect(jsonPath("$.message").value("Validation error"))
.andExpect(jsonPath("$.status").value("BAD_REQUEST"))
.andExpect(jsonPath("$.details", hasSize(1)))
.andExpect(jsonPath("$.details[0].*", hasSize(3)))
.andExpect(jsonPath("$.details[0].name", is("getGreeting.name")))
.andExpect(jsonPath("$.details[0].value", is("_")))
.andExpect(jsonPath("$.details[0].message", is("size must be between 2 and 10")));
}
}
你有2个问题,
1、需要用@Length
来验证String的长度,@Size
是验证集合中的项数,比如List
。如果您说它必须是 2 或 3 的整数,那么您需要 @Min(2) @Max(3)
。
2. 你的controller必须注解@Validated
.
有没有办法在@RequestParams 上对 javax 验证进行 spring 控制器单元测试。
我在控制器中有一个 get 方法,它使用 @Size 验证请求参数的大小。
@RequestMapping(value = "/getData", method = RequestMethod.GET)
public ResultgetData(
@Size(min=2, max=3)
@RequestParam String number)
有没有办法模拟 junit 测试大小验证器?我想验证大小为 <2 或 > 3 时返回的错误。
样本测试:
@RunWith(MockitoJUnitRunner.class) public class MyControllerTest {
private MockMvc mockMvc;
@InjectMocks
private MyController myControllerMock;
@Before
public void initTest() {
mockMvc = MockMvcBuilders.standaloneSetup(customerInsuranceControllerMock).setControllerAdvice(exceptionHandler).build();
}
@Test
public void getEmptyData() throws Exception{
mockMvc.perform(MockMvcRequestBuilders.get(
"/getData?number={number}"
, "")
.andExpect(MockMvcResultMatchers.status().isBadRequest()); // This is failing. It returns a success as javax @Size is not triggered.When a empty string is passed , it should be bad request
}
我也试过 spring 跑步者,但似乎还是失败了。
谢谢
如果我对您的问题的理解正确,您可以将 @RunWith
with SpringRunner
and @WebMvcTest
与您的控制器和异常处理程序一起使用 类。
由于您的问题没有显示您的控制器的外观,让我们考虑以下控制器,returns 给定名称的问候语:
@Data
public class Greeting {
private String content;
}
@Validated
@RestController
public class GreetingController {
@GetMapping(path = "/greeting", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Greeting> getGreeting(
@RequestParam @Size(min = 2, max = 10) String name) {
Greeting greeting = new Greeting();
greeting.setContent("Hello " + name + "!");
return ResponseEntity.ok(greeting);
}
}
现在让我们考虑 ConstraintViolationException
的异常处理程序,当某些验证失败时将抛出该异常处理程序:
@Data
public class ApiError {
private String message;
private HttpStatus status;
private Object details;
}
@Data
public class InvalidValue {
private String name;
private Object value;
private String message;
}
@ControllerAdvice
public class WebApiExceptionHandler {
@ExceptionHandler({ConstraintViolationException.class})
public ResponseEntity<Object> handleConstraintViolation(ConstraintViolationException ex,
WebRequest request) {
List<InvalidValue> invalidValues = ex.getConstraintViolations()
.stream()
.map(this::toInvalidValue)
.collect(toList());
ApiError apiError = new ApiError();
apiError.setMessage("Validation error");
apiError.setStatus(HttpStatus.BAD_REQUEST);
apiError.setDetails(invalidValues);
return new ResponseEntity<>(apiError, new HttpHeaders(), apiError.getStatus());
}
private InvalidValue toInvalidValue(ConstraintViolation violation) {
InvalidValue invalidValue = new InvalidValue();
invalidValue.setName(violation.getPropertyPath().toString());
invalidValue.setValue(violation.getInvalidValue());
invalidValue.setMessage(violation.getMessage());
return invalidValue;
}
}
有了这个,您可以编写如下所示的测试和期望:
@RunWith(SpringRunner.class)
@WebMvcTest({GreetingController.class, WebApiExceptionHandler.class})
public class GreetingControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
@SneakyThrows
public void getGreeting_shouldReturn200_whenNameIsValid() {
mockMvc.perform(
get("/greeting")
.param("name", "foo")
.accept(MediaType.APPLICATION_JSON))
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.*", hasSize(1)))
.andExpect(jsonPath("$.content").value("Hello foo!"));
}
@Test
@SneakyThrows
public void getGreeting_shouldReturn400_whenNameIsInvalid() {
mockMvc.perform(get("/greeting").param("name", "_"))
.andDo(print())
.andExpect(status().isBadRequest())
.andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.*", hasSize(3)))
.andExpect(jsonPath("$.message").value("Validation error"))
.andExpect(jsonPath("$.status").value("BAD_REQUEST"))
.andExpect(jsonPath("$.details", hasSize(1)))
.andExpect(jsonPath("$.details[0].*", hasSize(3)))
.andExpect(jsonPath("$.details[0].name", is("getGreeting.name")))
.andExpect(jsonPath("$.details[0].value", is("_")))
.andExpect(jsonPath("$.details[0].message", is("size must be between 2 and 10")));
}
}
你有2个问题,
1、需要用@Length
来验证String的长度,@Size
是验证集合中的项数,比如List
。如果您说它必须是 2 或 3 的整数,那么您需要 @Min(2) @Max(3)
。
2. 你的controller必须注解@Validated
.