这是我的控制器类。
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ValidController {
@GetMapping("/valid")
public ResponseEntity<String> valid(@RequestParam(required = false) @Valid @NotNull String firstName, @RequestParam(required = false) String lastName) {
System.out.println("firstName = " + firstName);
return ResponseEntity.ok(firstName);
}
}
这是使用 MockMvc、@SpringBootTest 的测试代码
@SpringBootTest(classes = ValidController.class)
@AutoConfigureMockMvc
public class ValidControllerTest {
@Autowired
private MockMvc mockMvc;
@Autowired
ServletModelAttributeMethodProcessor servletModelAttributeMethodProcessor;
@Test()
void validator_valid() throws Exception {
mockMvc.perform(get("/valid")
.param("lastName", "foo"))
.andExpect(status().is4xxClientError())
.andReturn();
}
}
所以问题就在这里。我知道我可以使用 @SpringBootTest 测试 @Valid 注释,但我不想简单地添加我制作的每个 bean。我想做的就是测试 ValidController,而不添加我制作的任何其他 bean。我怎样才能实现它?
我试过了
@Configuration
class TestConfig {
@Bean
public ServletModelAttributeMethodProcessor servletModelAttributeMethodProcessor() {
return new ServletModelAttributeMethodProcessor(true);
}
}
@SpringBootTest
(classes = {ValidController.class
, MethodValidationPostProcessor.class
, ValidationAutoConfiguration.class
, TestConfig.class
}
@AutoConfigureMockMvc
public class ValidControllerTest {
@Autowired
private MockMvc mockMvc;
@Autowired
ServletModelAttributeMethodProcessor servletModelAttributeMethodProcessor;
@Test()
void validator_valid() throws Exception {
mockMvc.perform(get("/valid")
.param("lastName", "foo"))
.andExpect(status().is4xxClientError())
.andReturn();
}
}
@Validated //this is added
@RestController
public class ValidController {
@GetMapping("/valid")
public ResponseEntity<String> valid(@RequestParam(required = false) @Valid @NotNull String firstName, @RequestParam(required = false) String lastName) {
return ResponseEntity.ok(firstName);
}
}
在这种情况下,测试抛出 ConstraintViolationException。但我不想在 Controller 类中添加@Validate,这在操作中是不必要的。如何在不使用@Validated的情况下在Controller中检查@Valid?
@WebMvcTest
的用途。它将仅引导所需的 MVC 部分和您的控制器,如果您有任何依赖项,请使用 @MockBean
来模拟它们。
其他一些技巧是不要使用参数,使用对象/dto 进行绑定和验证。让它变得更容易。
不要在控制器级别使用
@Validated
,因为它具有不同的目的,并且会导致不同的错误处理。 Spring Framework 6.2 包含对 MVC 和带注释参数的更好支持。
public class FormDto {
@NotNull
private String firstName;
@NotNull
private String lastName;
// Getters + Setters omitted
}
@RestController
public class ValidController {
@GetMapping("/valid")
public ResponseEntity<String> valid(@Valid FormDto form) {
System.out.println("firstName = " + form.getFirstName());
return ResponseEntity.ok(form.getFirstName());
}
}
测试
@WebMvcTest(ValidController.class)
public class ValidControllerTest {
@Autowired
private MockMvc mockMvc;
@Test()
void validator_valid() throws Exception {
mockMvc.perform(get("/valid")
.param("lastName", "foo"))
.andExpect(status().is4xxClientError())
.andReturn();
}
}
这基本上就是您所需要的。使用表单对象使验证变得更容易,然后在方法中变得简单
@RequestParam
。