Тестирование Spring MVC аннотации mapppings
С помощью 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")
?
Ответы
Ответ 1
Вы можете использовать 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);
}
}
С уважением,
Олли
Ответ 2
Решение Ollie охватывает тестирование конкретного примера аннотации, но как насчет более широкого вопроса о том, как тестировать все другие различные аннотации MV7. Мой подход (который можно легко распространить на другие аннотации) будет
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.