2009-05-14 18 views
18

Con Spring MVC, è possibile specificare che un particolare URL sarà gestito da un particolare metodo, ed è possibile specificare che particolari parametri saranno indirizzate verso particolari argomenti, in questo modo:Test Spring MVC mapppings annotazione

@Controller 
public class ImageController { 

    @RequestMapping("/getImage") 
    public String getImage(@RequestParam("imageId") int imageId, Map<String,Object> model) { 
     model.put("image",ImageService.getImage(imageId)); 
    } 

} 

Questo va tutto bene, ma ora voglio testare che una richiesta http con un parametro imageId invocherà correttamente questo metodo. In altre parole, voglio un test che si interromperà se rimuoverò o modificherò una qualsiasi delle annotazioni. C'è un modo per fare questo?

È facile verificare che getImage funzioni correttamente. Potrei semplicemente creare un ImageController e invocare getImage con argomenti appropriati. Tuttavia, questa è solo la metà del test. L'altra metà del test deve essere se getImage() sarà invocato dal framework Spring quando arriva una richiesta HTTP appropriata. Mi sento come se avessi bisogno anche di un test per questa parte, specialmente quando le mie annotazioni @RequestMapping diventano più complesse e invocano il complesso condizioni dei parametri.

Potrebbe mostrarmi un test che si interromperà se rimuovo la linea 4, @RequestMapping("getImage")?

+1

Non capisco perfettamente la tua domanda. Vuoi dire "Come creare un test unitario per i controllori MVC primaverili che utilizzano il mapping di annotazioni?"? –

+0

Siamo spiacenti. Voglio dire che voglio testare che l'annotazione sia corretta, e che una richiesta HTTP invochi davvero questo metodo. –

risposta

12

È possibile utilizzare il metodo AnnotationMethodHandlerAdapter e il relativo metodo handle a livello di programmazione. Questo risolverà il metodo per la richiesta data ed eseguirà. Sfortunatamente questo è un po 'indiretto. In realtà esiste una classe privata denominata ServletHandlerMethodResolver in AMHA, responsabile della risoluzione del metodo per una determinata richiesta. Ho appena presentato uno request for improvement su quell'argomento, perché mi piacerebbe davvero vederlo anche questo.

Nel frattempo è possibile utilizzare ad es. EasyMock per creare una simulazione della classe controller, aspettarsi che il metodo specificato venga invocato e consegnare tale simulazione a handle.

Controller:

@Controller 
public class MyController { 

    @RequestMapping("/users") 
    public void foo(HttpServletResponse response) { 

    // your controller code 
    } 
} 

prova:

public class RequestMappingTest { 

    private MockHttpServletRequest request; 
    private MockHttpServletResponse response; 
    private MyController controller; 
    private AnnotationMethodHandlerAdapter adapter; 


    @Before 
    public void setUp() { 

    controller = EasyMock.createNiceMock(MyController.class); 

    adapter = new AnnotationMethodHandlerAdapter(); 
    request = new MockHttpServletRequest(); 
    response = new MockHttpServletResponse(); 
    } 


    @Test 
    public void testname() throws Exception { 

    request.setRequestURI("/users"); 

    controller.foo(response); 
    EasyMock.expectLastCall().once(); 
    EasyMock.replay(controller); 

    adapter.handle(request, response, controller); 

    EasyMock.verify(controller); 
    } 
} 

saluti, Ollie

+0

Aggiungere una riga aggiuntiva: 'request.setAttribute (HandlerMapping.INTROSPECT_TYPE_LEVEL_MAPPING, Boolean.TRUE);' È necessario quando si utilizza la mappatura del livello del controller – takacsot

6

soluzione Ollie copre testare l'esempio specifico di un'annotazione ma per quanto riguarda la più ampia questione di come testare tutte le altre varie annotazioni Spring MVC. Il mio approccio (che può essere facilmente estesa ad altre annotazioni) sarebbe

import static org.springframework.test.web.ModelAndViewAssert.*; 

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration({/* include live config here 
    e.g. "file:web/WEB-INF/application-context.xml", 
    "file:web/WEB-INF/dispatcher-servlet.xml" */}) 
public class MyControllerIntegrationTest { 

    @Inject 
    private ApplicationContext applicationContext; 

    private MockHttpServletRequest request; 
    private MockHttpServletResponse response; 
    private HandlerAdapter handlerAdapter; 
    private MyController controller; 

    @Before 
    public void setUp() { 
     request = new MockHttpServletRequest(); 
     response = new MockHttpServletResponse(); 
     handlerAdapter = applicationContext.getBean(HandlerAdapter.class); 
     // I could get the controller from the context here 
     controller = new MyController(); 
    } 

    @Test 
    public void testFoo() throws Exception { 
     request.setRequestURI("/users"); 
     final ModelAndView mav = handlerAdapter.handle(request, response, 
      controller); 
     assertViewName(mav, null); 
     assertAndReturnModelAttributeOfType(mav, "image", Image.class); 
    } 
} 

Ho anche scritto un blog entry about integration testing Spring MVC annotations.

Problemi correlati