2009-05-14 17 views
18

Con Spring MVC, se puede especificar que una URL concreta será manejado por un método particular, y se puede especificar que los parámetros particulares se asignarán a los argumentos particulares, así:Prueba Spring MVC mapppings anotación

@Controller 
public class ImageController { 

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

} 

Este está todo bien, pero ahora quiero probar que una solicitud http con un parámetro imageId invocará este método correctamente. En otras palabras, quiero una prueba que se romperá si elimino o cambio alguna de las anotaciones. ¿Hay alguna forma de hacer esto?

Es fácil probar que getImage funciona correctamente. Podría simplemente crear un ImageController e invocar getImage con los argumentos apropiados. Sin embargo, esta es solo la mitad de la prueba. La otra mitad de la prueba debe ser si getImage() será invocado por Spring framework cuando entre una solicitud HTTP adecuada. Siento que también necesito una prueba para esta parte, especialmente porque mis anotaciones @RequestMapping se vuelven más complejas e invocan complejos condiciones del parámetro.

¿Podría mostrarme una prueba que se romperá si elimino la línea 4, @RequestMapping("getImage")?

+1

No entiendo completamente su pregunta. ¿Quiere decir "Cómo crear una prueba unitaria para los controladores Spring MVC que utilizan el mapeo de anotación"? –

+0

Lo siento. Quiero decir que quiero probar que la anotación es correcta y que una solicitud HTTP realmente invocará este método. –

Respuesta

12

Puede usar AnnotationMethodHandlerAdapter y su método handle mediante programación. Esto resolverá el método para la solicitud dada y lo ejecutará. Lamentablemente esto es un poco indirecto. En realidad, hay una clase privada llamada ServletHandlerMethodResolver en AMHA que se encarga de resolver el método para una solicitud determinada. Acabo de registrar un request for improvement sobre ese tema, ya que realmente me gustaría que esto sea posible también.

Mientras tanto, podría usar, por ejemplo, EasyMock para crear un simulacro de su clase de controlador, espere que se invoque el método dado y la mano que simula a handle.

controlador:

@Controller 
public class MyController { 

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

    // your controller code 
    } 
} 

prueba:

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

Saludos, Ollie

+0

Agregue una línea adicional: 'request.setAttribute (HandlerMapping.INTROSPECT_TYPE_LEVEL_MAPPING, Boolean.TRUE);' Se necesita cuando usa la asignación de nivel de controlador – takacsot

6

solución de Ollie cubre probar el ejemplo específico de una anotación, pero ¿qué pasa con la cuestión más amplia de cómo probar todas las otras varias anotaciones Spring MVC. Mi enfoque (que puede extenderse fácilmente a otras anotaciones) sería

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

También he escrito un blog entry about integration testing Spring MVC annotations.