隔离控制器测试无法实例化Pageable

时间:2014-03-04 14:27:11

标签: spring-mvc testing spring-data spring-mvc-test

我有一个Spring MVC控制器,它使用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;
    }

}

我想使用漂亮的Spring MVC测试支持来测试RequestMapping。为了使这些测试保持快速并与所有其他内容隔离开来,我不想创建完整的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());
    }

}

这种方法适用于其他控制器,它们不期望有一个Pageable,但是有了这个,我得到了一个很好的长Spring堆栈跟踪。它抱怨无法实例化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

问题:如何更改我的测试,以便正常进行神奇的无请求参数到页面转换?

注意:在实际应用中,一切正常。

4 个答案:

答案 0 :(得分:40)

可分页的问题可以通过提供自定义参数处理程序来解决。如果设置了此项,您将在ViewResolver异常(循环)中运行。为避免这种情况,您必须设置ViewResolver(例如匿名JSON ViewResolver类)。

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

答案 1 :(得分:35)

只需添加@EnableSpringDataWebSupport进行测试即可。多数民众赞成。

答案 2 :(得分:4)

对于春季启动,只需添加为我解决的ArgumentResolvers:

从触发错误的代码中:

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

对此有效:

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

答案 3 :(得分:0)

正好为此而困惑。
我想提供一个答案。

如果您不想测试Pageable功能,就不用管它了。
在Spring Boot 2.0.6上测试:

控制器的代码:

 @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
 @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());
    }
}

希望这对您有帮助...
问候
托马斯