2016-10-12 1 views
2

Je construis une application avec Spring Boot 1.4.1, Spring Data Jpa et Spring Data Test.Test de l'unité Spring MVC Controller qui retourne PagedResources

Je le contrôleur suivant avec lequel je veux rendre des comptes paginés:

@RequestMapping(method=RequestMethod.GET) 
public HttpEntity<PagedResources<Account>> getAccounts(
     Pageable pageable, 
     PagedResourcesAssembler assembler, 
     @RequestParam(value="name", required = false) String name, 
     @RequestParam(value="username", required = false) String username, 
     @RequestParam(value="email", required = false) String email, 
     @RequestParam(value="lastName", required = false) String lastName, 
     @RequestParam(value="size", required = true, defaultValue = "10") Integer size, 
     @RequestParam(value="page", required = true, defaultValue = "0") int page, 
     @RequestParam(value="sort", required = false, defaultValue = "username") String sort, 
     @RequestParam(value="direction", required = false, defaultValue = "asc") String direction, 
     UriComponentsBuilder uriBuilder, 
     HttpServletRequest request, 
     HttpServletResponse response) { 

    // form page request 
    AccountList list = null; 
    Page<Account> resultPage = null; 
    Direction sortDirection = Direction.ASC; 
    if(direction.equals("desc")) { 
     sortDirection = Direction.DESC; 
    } 
    PageRequest pReq = new PageRequest(page, size, sortDirection, sort); 

    resultPage = accountService.findAll(pReq); 

    return new ResponseEntity<>(assembler.toResource(resultPage), HttpStatus.OK); 
} 

Ma méthode d'essai est:

@Test 
public void getAccountsTest() throws Exception { 
    String uri = uriBase + "/accounts"; 

    List<Account> list = new ArrayList<Account>(); 
    list.add(accountOne); 
    list.add(accountTwo); 

    Page<Account> returnPage = new PageImpl<Account>(list, new PageRequest(0,10), list.size()); 

    when(accountService.findAll(any(PageRequest.class))).thenReturn(returnPage); 

    mockMvc.perform(get(uri)) 
      .andExpect(status().isOk()) 
      .andDo(print()) 
      .andExpect(content().contentType(TestUtil.APPLICATION_JSON_UTF8)) 
      .andExpect(jsonPath("$.accounts", hasSize(2))) 
      .andExpect(jsonPath("$.accounts[*].username", 
        hasItems(endsWith(accountOne.getUsername()), endsWith(accountTwo.getUsername())))) 
      .andExpect(jsonPath("$.accounts[*].email", 
        hasItems(endsWith(accountOne.getEmail()), endsWith(accountTwo.getEmail())))); 
} 

Mon problème est que quand je lance le test JUnit il se casse avec l'erreur

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:161) 
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:128) 
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:114) 
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:622) 
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:729) 
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 de.campuz.platform.rest.controller.AccountControllerTestDoc.getAccountsTest(AccountControllerTestDoc.java:93) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
at java.lang.reflect.Method.invoke(Method.java:498) 
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) 
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) 
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) 
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) 
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75) 
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86) 
at org.springframework.restdocs.JUnitRestDocumentation$1.evaluate(JUnitRestDocumentation.java:55) 
at org.junit.rules.RunRules.evaluate(RunRules.java:20) 
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84) 
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) 
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252) 
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) 
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) 
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) 
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) 
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) 
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) 
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) 
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) 
at org.junit.runners.ParentRunner.run(ParentRunner.java:363) 
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) 
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) 
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192) 

J'ai ajouté l'annotation @EnableSpringDataWebSupport à ma configuration Web mais l'erreur persiste toujours. Lors de l'exécution de l'application comme le contrôleur fonctionne très bien, je vais obtenir les comptes paginés en tant que réponse JSON. Mais je ne peux pas comprendre comment je peux tester mes contrôleurs.

Quelqu'un a-t-il une idée de comment résoudre ce problème spécifique ou comment tester les contrôleurs Spring MVC qui retournent le contenu paginé en général?

Merci à l'avance et meilleures salutations

Tim

Répondre

0

Je l'ai résolu en supprimant le paginable paginable du constructeur du contrôleur, parce que je ne l'ai pas besoin de toute façon. Ensuite, l'assembleur PagedResourcesAssembler a jeté l'erreur

org.springframework.beans.BeanInstantiationException: 
Failed to instantiate [org.springframework.data.web.PagedResourcesAssembler]: 
No default constructor found; nested exception is java.lang.NoSuchMethodException: 
org.springframework.data.web.PagedResourcesAssembler.<init>() 

Je fouillai un peu dans le thème de la ResourceAssembler et est venu avec la solution suivante:

Controller:

@RequestMapping(method=RequestMethod.GET) 
public ResponseEntity<PagedResources<AccountResource>> getAccounts(
     @RequestParam(value="name", required = false) String name, 
     @RequestParam(value="username", required = false) String username, 
     @RequestParam(value="email", required = false) String email, 
     @RequestParam(value="lastName", required = false) String lastName, 
     @RequestParam(value="size", required = true, defaultValue = "10") Integer size, 
     @RequestParam(value="page", required = true, defaultValue = "0") int page, 
     @RequestParam(value="sort", required = false, defaultValue = "username") String sort, 
     @RequestParam(value="direction", required = false, defaultValue = "asc") String direction, 
     UriComponentsBuilder uriBuilder, 
     HttpServletRequest request, 
     HttpServletResponse response) { 

    // Build page request 
    AccountList list = null; 
    Page<Account> resultPage = null; 
    Direction sortDirection = Direction.ASC; 
    if(direction.equals("desc")) { 
     sortDirection = Direction.DESC; 
    } 
    PageRequest pReq = new PageRequest(page, size, sortDirection, sort); 

    resultPage = accountService.findAll(pReq); 

    HateoasPageableHandlerMethodArgumentResolver resolver = new HateoasPageableHandlerMethodArgumentResolver(); 
    PagedResourcesAssembler<Account> accountPageAssembler = new PagedResourcesAssembler<Account>(resolver, null); 
    return new ResponseEntity<PagedResources<AccountResource>>(accountPageAssembler.toResource(resultPage, new AccountResourceAsm()), HttpStatus.OK); 
} 

Là où je crée la ressource Assembler avec le HateoasPageableHandlerMethodArgumentResolver pour transformer la page en PagedResource que je voulais retourner.

Ensuite, je pourrais enfin exécuter le test du contrôleur (comme vu dans la question) avec succès.

Cette answer m'a beaucoup aidé, merci Oliver Gierke et Patrick Cornelissen.

0

Ayant le même problème, je voulais éviter d'aller chercher "manuellement" le PagedResourcesAssembler dans le contrôleur.

L'ajout de ce à la classe d'essai fixée pour moi:

@Import(HateoasAwareSpringDataWebConfiguration.class)