Тестирование сопоставлений аннотаций Spring MVC

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

@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-запроса. Я чувствую, что мне также нужен тест для этой части, тем более что мои аннотации @RequestMapping становятся более сложными и вызывают сложные условия параметра.

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


person Brandon Yarbrough    schedule 14.05.2009    source источник
comment
Я не совсем понимаю ваш вопрос. Вы имеете в виду, как создать модульный тест для контроллеров Spring MVC, которые используют сопоставление аннотаций?   -  person victor hugo    schedule 14.05.2009
comment
Прости. Я имею в виду, что хочу проверить правильность аннотации и то, что HTTP-запрос действительно вызовет этот метод.   -  person Brandon Yarbrough    schedule 14.05.2009


Ответы (2)


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

А пока вы можете использовать, например, 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);
  }
}

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

person Oliver Drotbohm    schedule 15.05.2009
comment
Добавьте дополнительную строку: request.setAttribute(HandlerMapping.INTROSPECT_TYPE_LEVEL_MAPPING, Boolean.TRUE); Это необходимо, когда вы используете отображение уровня контроллера. - person takacsot; 27.06.2012

Решение Олли охватывает тестирование конкретного примера аннотации, но как насчет более широкого вопроса о том, как тестировать все другие различные аннотации 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);
    }
}

Я также написал запись в блоге об интеграционном тестировании аннотаций Spring MVC.

person scarba05    schedule 16.03.2010