Testing Spring @MVC annotations

前端 未结 3 452
执念已碎
执念已碎 2021-02-02 03:08

I ran into a problem the other day where a @Valid annotation was accidentally removed from a controller class. Unfortunately, it didn\'t break any of our tests. None of our un

3条回答
  •  梦如初夏
    2021-02-02 03:39

    I write integration tests for this kind of thing. Say you have a bean with validation annotations:

    public class MyForm {
        @NotNull
        private Long myNumber;
    
        ...
    }
    

    and a controller that handles the submission

    @Controller
    @RequestMapping("/simple-form")
    public class MyController {
        private final static String FORM_VIEW = null;
    
        @RequestMapping(method = RequestMethod.POST)
        public String processFormSubmission(@Valid MyForm myForm,
                BindingResult result) {
            if (result.hasErrors()) {
                return FORM_VIEW;
            }
            // process the form
            return "success-view";
        }
    }
    

    and you want to test that the @Valid and @NotNull annotations are wired correctly:

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration({"file:web/WEB-INF/application-context.xml",
        "file:web/WEB-INF/dispatcher-servlet.xml"})
    public class MyControllerIntegrationTest {
    
        @Inject
        private ApplicationContext applicationContext;
    
        private MockHttpServletRequest request;
        private MockHttpServletResponse response;
        private HandlerAdapter handlerAdapter;
    
        @Before
        public void setUp() throws Exception {
            this.request = new MockHttpServletRequest();
            this.response = new MockHttpServletResponse();
    
            this.handlerAdapter = applicationContext.getBean(HandlerAdapter.class);
        }
    
        ModelAndView handle(HttpServletRequest request, HttpServletResponse response)
                throws Exception {
            final HandlerMapping handlerMapping = applicationContext.getBean(HandlerMapping.class);
            final HandlerExecutionChain handler = handlerMapping.getHandler(request);
            assertNotNull("No handler found for request, check you request mapping", handler);
    
            final Object controller = handler.getHandler();
            // if you want to override any injected attributes do it here
    
            final HandlerInterceptor[] interceptors =
                handlerMapping.getHandler(request).getInterceptors();
            for (HandlerInterceptor interceptor : interceptors) {
                final boolean carryOn = interceptor.preHandle(request, response, controller);
                if (!carryOn) {
                    return null;
                }
            }
    
            final ModelAndView mav = handlerAdapter.handle(request, response, controller);
            return mav;
        }
    
        @Test
        public void testProcessFormSubmission() throws Exception {
            request.setMethod("POST");
            request.setRequestURI("/simple-form");
            request.setParameter("myNumber", "");
    
            final ModelAndView mav = handle(request, response);
            // test we're returned back to the form
            assertViewName(mav, "simple-form");
            // make assertions on the errors
            final BindingResult errors = assertAndReturnModelAttributeOfType(mav, 
                    "org.springframework.validation.BindingResult.myForm", 
                    BindingResult.class);
            assertEquals(1, errors.getErrorCount());
            assertEquals("", errors.getFieldValue("myNumber"));        
        }
    

    See my blog post on integration testing Spring's MVC annotations

提交回复
热议问题