2

I have a restcontroller inside a spring-application returning a list of objects...

@GetMapping
@Override
public ResponseEntity readAll(@QuerydslPredicate(root = Entity.class) Predicate predicate, Pageable pageable){
    ...
}

If I run it, everything works fine. I can filter the request by pageable and predicate. But if I run the junit test, it fails...

@Test
public void readAllTest(){
MockMvcBuilders.standaloneSetup(*myController*)
            .build().perform(MockMvcRequestBuilders.get(*myUri*)
                    .accept(MediaType.APPLICATION_JSON_UTF8_VALUE)
            )
            .andExpect(status().isOk())
            .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE));
}

Getting the following Errormessage... org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalStateException: No primary or default constructor found for interface com.querydsl.core.types.Predicate

Does anybody know how to test a restcontroller with a Pageable and Predicate?

Chris
  • 566
  • 1
  • 8
  • 20

3 Answers3

3
  1. Try to add on your test class annotation @Import(QuerydslWebConfiguration.class). It adds controller argument resolver for com.querydsl.core.types.Predicate into spring context.

  2. But after you'll face with an exception like:

    No primary or default constructor found for interface org.springframework.data.domain.Pageable.

  3. There is annotation, loads argument resolvers for both these interfaces. org.springframework.data.web.config.EnableSpringDataWebSupport

Addapted for your test class:

@RunWith(SpringRunner.class)
@WebMvcTest(*myController*.class)
@EnableSpringDataWebSupport
public class ControllerTest{

  @Test
  public void readAllTest(){
    MockMvcBuilders.standaloneSetup(*myController*)
            .build().perform(MockMvcRequestBuilders.get(*myUri*)
                    .accept(MediaType.APPLICATION_JSON_UTF8_VALUE)
            )
            .andExpect(status().isOk())
            .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE));
  }
}
Niki.Max
  • 163
  • 1
  • 5
0

For now, you just need to setup mockMvc with ApplicationContext, like

@RunWith(SpringRunner.class)
@SpringBootTest
public class ControllerTest {

  @Autowired
  private WebApplicationContext webApplicationContext;

  @Test
  public void readAllTest() throws Exception {
    MockMvcBuilders.webAppContextSetup(this.webApplicationContext).build()
        .perform(MockMvcRequestBuilders.get("YOUR_URI")
        .accept(MediaType.APPLICATION_JSON_UTF8_VALUE))
        .andExpect(status().isOk())
        .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE));
  }

}

https://docs.spring.io/spring/docs/current/spring-framework-reference/testing.html#spring-mvc-test-server

bmstefanski
  • 21
  • 1
  • 6
0

If anyone is facing this not just with tests, but also with normal application run, this might be due to web application not being configured by Spring Boot. For instance my project had a SwaggerConfig extending WebMvcConfigurationSupport:

@Configuration
@EnableSwagger2
public class SwaggerConfig extends WebMvcConfigurationSupport {
    // Docket bean
    
    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
    }
}

I removed the inheritance and manual resource handlers, and it works fine now.

Note: In addition to WebMvcConfigurationSupport, things like @EnableWebMvc & WebMvcConfigurer might also lead to Spring Boot's web autoconfiguration not being used.

Sources: Another SO Answer, Swagger Issue comment

aksh1618
  • 2,245
  • 18
  • 37