'SCC doesn't support Pageable?

I am using spring cloud contract (1.1.0) but i am completly stuck when I want to use Pageable

http://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/domain/Pageable.html

The following example is working, without the pageable

@GetMapping("/employees")
@Timed
public List<EmployeeDTO> getAllEmployees() {
    log.debug("REST request to get all Employees");
    List<Employee> employees = employeeRepository.findAll();
    return employeeMapper.employeesToEmployeeDTOs(employees);
}

And this one is using the pageable

@GetMapping("/employees")
@Timed
public ResponseEntity<List<EmployeeDTO>> getAllEmployees(@ApiParam Pageable pageable)
    throws URISyntaxException {
    log.debug("REST request to get a page of Employees");
    Page<Employee> page = employeeRepository.findAll(pageable);
    HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/employees");
    return new ResponseEntity<>(employeeMapper.employeesToEmployeeDTOs(page.getContent()), headers, HttpStatus.OK);
}

My contract is here. Working for the first example, not for the second

import org.springframework.cloud.contract.spec.Contract
[
Contract.make {
    name("get all")
    request {
        method 'GET'
        url('/api/employees?sort=id,desc')

    }
    response {
        status 200
        body([
            [id : 1,
            firstName : value(consumer('test'), producer(regex('[a-zA-Z0-9]{1,255}'))),
            lastName : value(consumer('test'), producer(regex('[a-zA-Z0-9]{1,255}'))),
            phoneNumber : value(consumer('test'), producer(regex('[a-zA-Z0-9]{1,255}'))),
            salary : value(consumer(1000), producer(regex('[0-9]{1,10}'))),
            commissionPct : value(consumer(1000), producer(regex('[0-9]{1,10}')))
            ],
            [id : 2,
            firstName : value(consumer('test2'), producer(regex('[a-zA-Z0-9]{1,255}'))),
            lastName : value(consumer('test2'), producer(regex('[a-zA-Z0-9]{1,255}'))),
            phoneNumber : value(consumer('test2'), producer(regex('[a-zA-Z0-9]{1,255}'))),
            salary : value(consumer(2000), producer(regex('[0-9]{1,10}'))),
            commissionPct : value(consumer(2000), producer(regex('[0-9]{1,10}')))
        ]

        ])
        headers {
            contentType('application/json;charset=UTF-8')
        }
    }
}
]

And the stack trace :

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.data.domain.Pageable]: Specified class is an interface
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:99)
    at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.createAttribute(ModelAttributeMethodProcessor.java:142)
    at org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor.createAttribute(ServletModelAttributeMethodProcessor.java:80)
    at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:102)
    at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121)
    at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:160)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:129)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:116)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:65)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
    at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:167)
    at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:134)
    at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:155)
    at com.jayway.restassured.module.mockmvc.internal.MockMvcRequestSenderImpl.performRequest(MockMvcRequestSenderImpl.java:174)
    at com.jayway.restassured.module.mockmvc.internal.MockMvcRequestSenderImpl.sendRequest(MockMvcRequestSenderImpl.java:404)
    at com.jayway.restassured.module.mockmvc.internal.MockMvcRequestSenderImpl.get(MockMvcRequestSenderImpl.java:582)
    at com.jayway.restassured.module.mockmvc.internal.MockMvcRequestSenderImpl.get(MockMvcRequestSenderImpl.java:79)
    at com.jayway.restassured.module.mockmvc.internal.MockMvcRequestSpecificationImpl.get(MockMvcRequestSpecificationImpl.java:744)
    at com.jayway.restassured.module.mockmvc.internal.MockMvcRequestSpecificationImpl.get(MockMvcRequestSpecificationImpl.java:66)
    at org.springframework.cloud.contract.verifier.tests.EmployeeTest.validate_get_all(EmployeeTest.java:47)

What should I do ? What should I modify to make it works ?



Solution 1:[1]

But what exactly are you trying to achieve? What you've presented in the example is actually a single body that contains two elements. Is that what you wanted to send? Or would you want with the first call the first element and then the second. If that's the case then you do a stateful case with scenarios http://cloud.spring.io/spring-cloud-contract/1.0.x/#_scenarios . You'd need to do 2 separate contracts.

Another question is if you really need to test if paging works. You want to test that the contract is valid and it will be by sending the request once only (or I'm missing sth that you want to test?).

UPDATE:

I think it's related to Spring Data + Rest Assured. Please check out this issue - Isolated Controller Test can't instantiate Pageable

Solution 2:[2]

With the Pageable parameter, Spring Data Rest recognizes sorting parameters : http://docs.spring.io/spring-data/rest/docs/current/reference/html/#paging-and-sorting.sorting

But during unit tests with Contract, Pageable can't be created since it's an interface...

Solution 3:[3]

RestAssuredMockMvc must be injected with PageableHandler. The controller takes in @PageableDefault. If PageableHandlerMethodArgumentResolver is not provided, it fails to find the implementation class of Pageable Interface.

RestAssuredMockMvc.standaloneSetup(MockMvcBuilders.standaloneSetup(configurableProductController).setCustomArgumentResolvers(new PageableHandlerMethodArgumentResolver()));

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Community
Solution 2 SebastienRen
Solution 3 bimarsh sharma