Как 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, кроме того, что описал Саша, за исключением того, что вы должны определенно утверждать модель.