web-dev-qa-db-fra.com

Le test de contrôleur isolé ne peut pas instancier Pageable

J'ai un contrôleur Spring MVC qui utilise le support de pagination de 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;
    }

}

Et j'aimerais tester RequestMapping à l'aide du support de test MVC de Nice Spring. Afin de garder ces tests rapides et isolés de tout ce qui se passe, je ne veux pas créer le champ ApplicationContext complet:

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

}

Cette approche fonctionne bien avec les autres contrôleurs, qui ne s’attendent pas à un pageable, mais avec celui-ci, j’obtiens l’un de ces stacktraces de Nice long Spring. Il se plaint de ne pas pouvoir instancier 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: Comment puis-je modifier mon test pour que la conversion magique No-Request-Parameter-To-Pagable soit correctement?

Remarque: dans l'application réelle, tout fonctionne correctement.

33
Jens Schauder

Le problème de pagination peut être résolu en fournissant un gestionnaire d'arguments personnalisé. Si cette option est définie, vous exécuterez une exception ViewResolver (boucle). Pour éviter cela, vous devez définir un ViewResolver (une classe JSON ViewResolver anonyme, par exemple).

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

Ajoutez simplement @EnableSpringDataWebSupport pour le test. C'est tout.

33
user2031839

Pour le démarrage du printemps, il suffit d’ajouter les ArgumentsResolvers résolus pour moi: 

Du code qui a déclenché l'erreur: 

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

Pour cela, qui fonctionne: 

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

Je suis tombé sur ça.
.__ Je voulais apporter une réponse à cette question. 

Si vous ne voulez pas tester la fonctionnalité Pageable, laissez-la de côté.
Testé sur Spring Boot 2.0.6:

Code du contrôleur:

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

Code de test:

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

J'espère que cela t'aides ...
Sincères amitiés
Thomas

0
Thomas Lang