Isolated Controller Test can't instantiate Pageable
Solution 1
Original answer:
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();
Updated (2020):
It is not necessary to add the ViewResolver
anymore.
Regarding the parallel answer:
It does not solve the problem for the original question to have this test running without ApplicationContext
and/or friends.
Solution 2
Just add @EnableSpringDataWebSupport for test. Thats it.
Solution 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();
Jens Schauder
Softwaredeveloper, Blogger, nitpick. Spring Data committer.
Updated on June 05, 2022Comments
-
Jens Schauder almost 2 years
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.
-
Bastian Voigt over 6 yearsI added
@EnableSpringDataWebSupport
annotation to my test class, but this did not have any effect. Could you give some more details on how this is supposed to work? -1 for now -
K.Nicholas almost 6 yearsShould be the correct answer. If your unit test is still failing check to see if the error returned is different. Could be you've moved on to a different bug.
-
Catarina Nogueira almost 6 yearswhy this works? Can you give more explanation so i can understand better how to overcome situations when it happens again? :-)
-
Dalibor Filus almost 6 yearsAdding @EnableSpringDataWebSupport to the test class doesn't solve it for me - still the same exception:
No primary or default constructor found for interface org.springframework.data.domain.Pageable
. Is this dependent on some package? -
Dalibor Filus almost 6 yearsSooo.... I had to remove @DataJpaTest and move BackendApplication upper one level.
-
Yu Tian Toby over 2 yearsnot working for my case