2009-05-14 4 views
18

С Spring MVC, можно указать, что конкретный URL будет обрабатываться с помощью конкретного способа, и вы можете указать, что конкретные параметры сопоставляются с конкретными аргументами, например, так:Тестирование Spring MVC аннотаций mapppings

@Controller 
public class ImageController { 

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

} 

Этот все хорошо и хорошо, но теперь я хочу проверить, что HTTP-запрос с параметром imageId вызовет этот метод правильно. Другими словами, я хочу тест, который сломается, если я удалю или изменю любые аннотации. Есть ли способ сделать это?

Легко проверить, что getImage работает правильно. Я мог бы просто создать ImageController и вызвать getImage с соответствующими аргументами. Однако это всего лишь половина теста. Другая половина теста должна состоять в том, будет ли getImage() вызываться средой Spring, когда приходит соответствующий HTTP-запрос. Я чувствую, что мне также нужен тест для этой части, тем более что мои аннотации становятся более сложными и вызывают сложный параметров.

Не могли бы вы показать мне тест, который сломается, если я удалю строку 4, @RequestMapping("getImage")?

+1

Я не совсем понимаю ваш вопрос. Вы имеете в виду «Как создать модульный тест для Spring MVC Controllers, который использует сопоставление аннотаций?»? –

+0

Извините. Я хочу сказать, что хочу проверить правильность аннотации и что HTTP-запрос действительно вызовет этот метод. –

ответ

12

Вы можете использовать программный код AnnotationMethodHandlerAdapter и его метод handle. Это решит метод для данного запроса и выполнит его. К сожалению, это немного косвенно. На самом деле в AMHA есть частный класс под названием ServletHandlerMethodResolver, который отвечает за простое решение метода для данного запроса. Я только что подал request for improvement по этой теме, так как я действительно хотел бы видеть это возможным.

Тем временем вы могли бы использовать, например. EasyMock, чтобы создать макет вашего класса контроллера, ожидайте, что данный метод будет вызван, и передайте его в handle.

Контроллер:

@Controller 
public class MyController { 

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

    // your controller code 
    } 
} 

Тест:

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

С уважением, Олли

+0

Добавьте дополнительную строку: 'request.setAttribute (HandlerMapping.INTROSPECT_TYPE_LEVEL_MAPPING, Boolean.TRUE);' Это необходимо, когда вы используете сопоставление уровня контроллера – takacsot

6

решение Олли охватывает тестирование конкретный пример аннотации, но что о более широком вопросе о том, как проверить все другие различные аннотации Spring MVC. Мой подход (который может быть легко расширена на другие аннотации) будет

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

Я также написал blog entry about integration testing Spring MVC annotations.