unit test Spring MissingServletRequestParameterException JSON response

家住魔仙堡 提交于 2019-12-05 16:43:15

This is because Spring Boot has auto-configured an exception handler org.springframework.boot.autoconfigure.web.BasicErrorController which is probably not present in your unit tests. A way to get it will be to use the Spring Boot testing support related annotations:

@SpringApplicationConfiguration
@WebIntegrationTest

More details are here

Update: You are absolutely right, the behavior is very different in UI vs in test, the error pages which respond to status codes are not correctly hooked up in a non-servlet test environment. Improving this behavior can be a good bug to open for Spring MVC and/or Spring Boot.

For now, I have a workaround which simulates the behavior of BasicErrorController the following way:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {RestApplication.class, TestConfiguration.class})
@WebIntegrationTest
public class PostControllerTest {

    private MockMvc mockMvc;

    @Autowired
    private WebApplicationContext webApplicationContext;

    @Autowired
    private FilterChainProxy springSecurityFilterChain;

    @Before
    public void setUp() {
        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
                .addFilter(springSecurityFilterChain)
                .build();
    }  

    @Test
    public void bookmarkMissingActionTypeParam() throws Exception{
        // @formatter:off
        mockMvc.perform(
                    post("/post/action/bookmark")
                        .accept(MediaType.APPLICATION_JSON)
                        .param("postId", "55ab8831036437e96e8250b6")
                        )
                .andDo(print())
                .andExpect(status().isBadRequest())
                .andExpect(jsonPath("$.exception", containsString("MissingServletRequestParameterException")));
        // @formatter:on
    }
}
     @Configuration
    public static class TestConfiguration {


        @Bean
        public ErrorController errorController(ErrorAttributes errorAttributes) {
            return new ErrorController(errorAttributes);
        }
    }
@ControllerAdvice
class ErrorController extends BasicErrorController {

    public ErrorController(ErrorAttributes errorAttributes) {
        super(errorAttributes);
    }

    @Override
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
        return super.error(request);
    }
}

What I am doing here is adding a ControllerAdvice which handles the Exception flow and delegates back to the BasicErrorController. This would atleast make the behavior consistent for you.

Vishal

Originally, it should fix the error by @ResponseBody tag when defining your REST controller method. it will fix json error in the test class. But, as you are using spring boot, you will define the controller class with @RestController and it should automatically take care of the error without defining @Controller and @ResponseType tags.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!