Как unit test a Spring аннотированный контроллер MVC?
Я следую учебнику Spring 2.5 и стараюсь, в то же время, обновлять код/настройку до Spring 3.0.
В Spring 2,5 У меня был HelloController (для справки):
public class HelloController implements Controller {
protected final Log logger = LogFactory.getLog(getClass());
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
logger.info("Returning hello view");
return new ModelAndView("hello.jsp");
}
}
И тест JUnit для HelloController (для справки):
public class HelloControllerTests extends TestCase {
public void testHandleRequestView() throws Exception{
HelloController controller = new HelloController();
ModelAndView modelAndView = controller.handleRequest(null, null);
assertEquals("hello", modelAndView.getViewName());
}
}
Но теперь я обновил контроллер до Spring 3.0, и теперь он использует аннотации (я также добавил сообщение):
@Controller
public class HelloController {
protected final Log logger = LogFactory.getLog(getClass());
@RequestMapping("/hello")
public ModelAndView handleRequest() {
logger.info("Returning hello view");
return new ModelAndView("hello", "message", "THIS IS A MESSAGE");
}
}
Зная, что я использую JUnit 4.9, может кто-нибудь объяснить мне, как unit test этот последний контроллер?
Ответы
Ответ 1
Одним из преимуществ MVC на основе аннотаций является то, что они могут быть протестированы простым способом, например:
import org.junit.Test;
import org.junit.Assert;
import org.springframework.web.servlet.ModelAndView;
public class HelloControllerTest {
@Test
public void testHelloController() {
HelloController c= new HelloController();
ModelAndView mav= c.handleRequest();
Assert.assertEquals("hello", mav.getViewName());
...
}
}
Есть ли проблема с этим подходом?
Для более продвинутого тестирования интеграции в Spring документации можно найти org.springframework.mock. веб.
Ответ 2
При использовании mvc: annotation-driven у вас должно быть 2 этапа: сначала вы разрешаете запрос обработчику с помощью HandlerMapping, тогда вы можете выполнить метод с помощью этого обработчика через HandlerAdapter. Что-то вроде:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("yourContext.xml")
public class ControllerTest {
@Autowired
private RequestMappingHandlerAdapter handlerAdapter;
@Autowired
private RequestMappingHandlerMapping handlerMapping;
@Test
public void testController() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest();
// request init here
MockHttpServletResponse response = new MockHttpServletResponse();
Object handler = handlerMapping.getHandler(request).getHandler();
ModelAndView modelAndView = handlerAdapter.handle(request, response, handler);
// modelAndView and/or response asserts here
}
}
Это работает с Spring 3.1, но я предполагаю, что какой-то вариант этого должен существовать для каждой версии. Глядя на код Spring 3.0, я бы сказал, что DefaultAnnotationHandlerMapping и AnnotationMethodHandlerAdapter должны сделать трюк.
Ответ 3
Вы также можете посмотреть другие веб-теги, которые не зависят от Spring, например HtmlUnit, или Selenium. Вы не найдете более надежной стратегии только с JUnit, кроме того, что описал Саша, за исключением того, что вы должны определенно утверждать модель.