Isolated Controller Test can't instantiate Pageable

馋奶兔 提交于 2019-11-27 03:02:19

问题


I have a Spring MVC Controller which uses Pagination Support of Spring-Data:

@Controller
public class ModelController {

    private static final int DEFAULT_PAGE_SIZE = 50;

    @RequestMapping(value = "/models", method = RequestMethod.GET)
    public Page<Model> showModels(@PageableDefault(size = DEFAULT_PAGE_SIZE) Pageable pageable, @RequestParam(
            required = false) String modelKey) {

//..
        return models;
    }

}

And I'd like to test the RequestMapping using the nice Spring MVC Test Support. In order to keep these tests fast and isolated from all the other stuff going on, I do not want to create the complete ApplicationContext:

public class ModelControllerWebTest {
    private MockMvc mockMvc;

    @Before
    public void setup() {
        ModelController controller = new ModelController();
        mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
    }

    @Test
    public void reactsOnGetRequest() throws Exception {
        mockMvc.perform(get("/models")).andExpect(status().isOk());
    }

}

This approach works fine with other Controllers, that do not expect a Pageable, but with this one I get one of these nice long Spring stacktraces. It complains about not being able to instantiate Pageable:

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.data.domain.Pageable]: Specified class is an interface
at   
.... lots more lines

Question: How do I change my test so the magic No-Request-Parameter-To-Pageable conversion happens properly?

Note: In the actual application everything is working fine.


回答1:


The problem with pageable can be solved by providing a custom argument handler. If this is set you will run in a ViewResolver Exception (loop). To avoid this you have to set a ViewResolver (an anonymous JSON ViewResolver class for example).

mockMvc = MockMvcBuilders.standaloneSetup(controller)
            .setCustomArgumentResolvers(new PageableHandlerMethodArgumentResolver())
            .setViewResolvers(new ViewResolver() {
                @Override
                public View resolveViewName(String viewName, Locale locale) throws Exception {
                    return new MappingJackson2JsonView();
                }
            })
            .build();



回答2:


Just add @EnableSpringDataWebSupport for test. Thats it.




回答3:


For spring boot simply adding the ArgumentResolvers solved for me:

From code which triggered the error:

this.mockMvc = MockMvcBuilders.standaloneSetup(weightGoalResource).build();

To this, which works:

this.mockMvc = MockMvcBuilders.standaloneSetup(weightGoalResource)
            .setCustomArgumentResolvers(new PageableHandlerMethodArgumentResolver())
            .build();



回答4:


Just stumpled upon this.
I wanted to provide an answer to this.

If you don´t want to test for Pageable functionality just leave it out.
Tested on Spring Boot 2.0.6:

Controller´s code:

 @RequestMapping(value = "/searchbydistance/{distance}/{address}/page")
 public String searchByDistance(@PathVariable int distance, 
                                @PathVariable @NonNull String address, 
                                Model model, Pageable pageable, 
                                Locale locale, 
                                RedirectAttributes redirectAttributes) {
 }

Test code:

 @Test
 @WithMockUser(username = "user", authorities = {"AdminRole"})
 public void testSearchByDistance() {

    try {
        UriComponents uri = UriComponentsBuilder.fromUriString("/joboffers/searchbydistance/{distance}/{address}/page").buildAndExpand(10, "Deggendorf");
        this.mockMvc.perform(get(uri.toUri())).andExpect(status().isOk());
    } catch (Exception e) {
        log.error(e.getMessage());
    }
}

Hope this helps ...
Kind regards
Thomas



来源:https://stackoverflow.com/questions/22174665/isolated-controller-test-cant-instantiate-pageable

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