Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to enable controller parameter validation for standalone MockMvc

Tags:

Controller

@RestController
@Validated
class MyController {

    @GetMapping("/foo")
    public String unwrapped(@Min(1) @RequestParam("param") int param) {
        return Integer.toString(param);
    }

    @GetMapping("/bar")
    public String wrapped(@ModelAttribute @Valid Wrapper bean) {
        return Integer.toString(bean.param);
    }

    static class Wrapper {

        @Min(1)
        int param;

        public void setParam(final int param) {
            this.param = param;
        }
    }
}

Test

public class MyControllerTest {

    MyController controller = new MyController();
    MockMvc mockMvc = MockMvcBuilders
            .standaloneSetup(this.controller)
            .build();

    @Test // fails
    public void unwrapped() throws Exception {
        this.mockMvc.perform(get("/foo")
                .param("param", "0"))
                .andExpect(status().isBadRequest());
    }

    @Test // passes
    public void wrapped() throws Exception {
        this.mockMvc.perform(get("/bar")
                .param("param", "0"))
                .andExpect(status().isBadRequest());
    }
}

To enable (unwrapped) method parameter validation in spring the controller has to be annotated with @Validated and the MethodValidationPostProcessor must be added to the context.
Is it possible to add the MethodValidationPostProcessor bean to the standalone setup ?
The question might be reduced to how to add a BeanPostProcessor to a standalone MockMvc setup ?

like image 371
Bax Avatar asked Mar 07 '18 20:03

Bax


1 Answers

Is it possible to add the MethodValidationPostProcessor bean to the standalone setup ?

No, that is unfortunately not possible when using MockMvcBuilders.standaloneSetup() since that creates a StubWebApplicationContext behind the scenes which does not support BeanPostProcessors.

Once SPR-6380 has been addressed (currently in the Spring Framework 5.x backlog), you will no longer need to rely on the MethodValidationPostProcessor. However, in the interim you will need to switch to the use of MockMvcBuilders.webAppContextSetup() in order to be able to test the behavior added to you controller via MethodValidationPostProcessor.

Original Erroneous Suggestion

I don't think it's possible to do that directly; however, you could create a custom subclass of StandaloneMockMvcBuilder that overrides the initWebAppContext() method, delegates to super.initWebAppContext() to create the WebApplicationContext, and then registers the MethodValidationPostProcessor bean programmatically via org.springframework.test.web.servlet.setup.StubWebApplicationContext.addBean(String, Object).

like image 80
Sam Brannen Avatar answered Sep 20 '22 13:09

Sam Brannen