【问题标题】:Testing @Validated RestController in standalone MockMvc not working在独立的 MockMvc 中测试 @Validated RestController 不起作用
【发布时间】:2019-08-03 19:58:07
【问题描述】:

我用 @Validated 注解了 RestController 以验证路径变量/请求参数:

@RestController
@Validated
public class MainController implements ApplicationListener<ApplicationReadyEvent> {

    @Autowired
    private CarsService carsService;

    @ExceptionHandler
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public void handleException(ConstraintViolationException ex) {}

    @GetMapping(
            value = "/",
            produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<?> getCars(
            @RequestParam(value = "offset", defaultValue = "0") @PositiveOrZero
                    Integer offset,
            @RequestParam(value = "limit", defaultValue = paginationLimitDefault)
            @Positive @Max(paginationLimitMax)
                    Integer limit) {
        ...
        ...
        Map responseBody = new HashMap<String, Object>();
        responseBody.put("offset", offset);
        responseBody.put("limit", limit);
        return ResponseEntity.status(HttpStatus.OK).body(responseBody);
    }
}

现在,我想使用独立的 mockMvc 对控制器级别进行单元测试:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
@ActiveProfiles("test")
public class TestMainController {

    @InjectMocks
    private MainController mainController;

    @Mock
    private CarsService carsServiceMock;

    private MockMvc mockMvc;

    @Before
    public void initMocks() {
        MockitoAnnotations.initMocks(this);
        mockMvc = MockMvcBuilders.standaloneSetup(mainController).build();
    }

    @Test
    public void getCarsInvalidOffset() throws Exception {
        mockMvc.perform(get("/")
                .param("offset", "-1"))
                .andExpect(status().isBadRequest());
    }

    @Test
    public void getCarsInvalidLimit() throws Exception {
        mockMvc.perform(get("/")
                .param("limit", "0"))
                .andExpect(status().isBadRequest());
        mockMvc.perform(get("/")
                .param("limit", "-1"))
                .andExpect(status().isBadRequest());
        mockMvc.perform(get("/")
                .param("limit", "101"))
                .andExpect(status().isBadRequest());
    }
}   

问题是带有无效参数的测试(上面的代码 sn-p 中的两个测试)应该返回错误请求,实际上返回 200 OK,结果测试失败。
我该如何解决? 谢谢。

【问题讨论】:

  • 您的验证是否在测试环境之外工作?
  • 是的,它确实有效。
  • 为什么要为此启动 Spring Boot 测试?从内存中,您可以使用WebMvcTest 并自动连接MockMvc,如果您需要设置独立设置以拥有验证器,它将起作用。
  • 我也试过WebMvcTest,没用。

标签: java spring spring-boot spring-web spring-validator


【解决方案1】:

我怀疑因为你在模拟 MainController,@Validated 没有生效。试试这个:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
@ActiveProfiles("test")
public class TestMainController {

    @Autowired
    private MainController mainController;

    @MockBean
    private CarsService carsServiceMock;

    @Autowired
    private WebApplicationContext context;

    private MockMvc mockMvc;

    @Before
    public void initMocks() {
        mockMvc = MockMvcBuilders.webAppContextSetup(context)
        .build();
    } 

【讨论】:

  • 这不是一个独立的设置。
【解决方案2】:

standaloneSetup 无法做到这一点。

更多详情请参考:How to enable controller parameter validation for standalone MockMvc

对于我们需要的@Validated 测试用例:

MockMvcBuilders.webAppContextSetup() 

【讨论】:

    猜你喜欢
    • 2017-01-23
    • 1970-01-01
    • 1970-01-01
    • 2020-06-20
    • 2018-08-10
    • 2021-11-22
    • 2017-05-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多