how to treat controller exception with mockmvc

23,758

Solution 1

Did you try to use a custom ExceptionHandler like here? : https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc

If you do so you can return custom HTTP response codes and verify them in your test.

Solution 2

Easier way is to inject @ExceptionHandler into your Spring Test Context or it throws exception right in MockMvc.perform() just before .andExpect().

@ContextConfiguration(classes = { My_ExceptionHandler_AreHere.class })
@AutoConfigureMockMvc
public class Test {
    @Autowired
    private MockMvc mvc;

    @Test
    public void test() {
        RequestBuilder requestBuilder = MockMvcRequestBuilders.post("/update")
                .param("branchId", "13000")
                .param("triggerId", "1");
        MvcResult mvcResult = mvc.perform(requestBuilder)
                .andExpect(MockMvcResultMatchers.status().is4xxClientError())
                .andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON_UTF8))
                .andExpect(__ -> Assert.assertThat(
                        __.getResolvedException(),
                        CoreMatchers.instanceOf(SecurityException.class)))
                .andReturn();
}

That way MvcResult.getResolvedException() holds @Controller's exception!

Share:
23,758
tzortzik
Author by

tzortzik

Updated on July 09, 2022

Comments

  • tzortzik
    tzortzik almost 2 years

    I am using MockMVC to test my controller.

    I have the following controller:

    public class A{
    
        ...
    
        @RequestMapping("/get")
        public List<ADTO> get(@RequestParam(defaultValue = "15", required = false) Integer limit) throws IOException {
            if(limit <= 0 || limit >= 50){
                throw new IllegalArgumentException();
            }
            ...
            return aDTOs;
        }
    
    }
    

    And my current test looks like this:

    @Test
    public void testGetAllLimit0() throws Exception {
        mockMvc.perform(get("/A/get")
                .param("limit","0")
                )
                .andDo(print())
                .andExpect(...);
    }
    

    I am instantiating MockMVC with this:

    @Before
    public void setup() {
        this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
    }
    

    How can I take care of that exception thrown in my controller?

    Later Edit:

    I'm not sure what happened in my code recently but it passes the test:

    @Test
    public void testGetAllLimit0() throws Exception {
        mockMvc.perform(get("/A/get")
                .param("limit","0")
                )
                .andDo(print())
                .andExpect(status().is(500));
    }
    

    It still passes if I replace is(500) with isOk(). And this is not good, I should check somehow for that exception.

    If I run a gradle build I get this:

    org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalArgumentException