Статьи

Интеграционные тесты Spring MVC

Подход к тестированию интеграции в контроллерах Spring MVC заключается в использовании поддержки тестирования интеграции, предоставляемой Spring.

В Junit4 эта поддержка состоит из пользовательского Runit Junit, называемого SpringJunit4ClassRunner, и пользовательской аннотации для загрузки соответствующей конфигурации Spring.

Пример Интеграционного теста будет выглядеть следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:/META-INF/spring/webmvc-config.xml", "contextcontrollertest.xml"})
public class ContextControllerTest {
 
    @Autowired
    private RequestMappingHandlerAdapter handlerAdapter;
 
    @Autowired
    private RequestMappingHandlerMapping handlerMapping;
     
    ......
  
 @Test
 public void testContextController() throws Exception{
  MockHttpServletRequest httpRequest = new MockHttpServletRequest("POST","/contexts");
  httpRequest.addParameter("name", "context1");
   
  httpRequest.setAttribute(DispatcherServlet.OUTPUT_FLASH_MAP_ATTRIBUTE,new FlashMap());
  MockHttpServletResponse response = new MockHttpServletResponse();
  Authentication authentication = new UsernamePasswordAuthenticationToken(new CustomUserDetails(..), null);
  SecurityContextHolder.getContext().setAuthentication(authentication);
 
  Object handler = this.handlerMapping.getHandler(httpRequest).getHandler();
  ModelAndView modelAndView = handlerAdapter.handle(httpRequest, response, handler);
  assertThat(modelAndView.getViewName(), is("redirect:/contexts"));
 }
}

Я использовал MockHttpServletRequest для создания фиктивного POST-запроса к URI «/ contexts» и добавил некоторые детали аутентификации для деталей, связанных с Spring Security, которые будут доступны в контроллере. ModelAndView, возвращаемый контроллером, проверяется, чтобы убедиться, что возвращаемое имя представления соответствует ожидаемому.

Лучший способ выполнить интеграцию, связанную с контроллером, — это использование относительно нового проекта Spring под названием Spring-test-mvc , который обеспечивает свободный способ тестирования потоков контроллера. Те же тесты, что и выше, выглядят следующим образом с Spring-test-mvc:

01
02
03
04
05
06
07
08
09
10
@Test
public void testContextController() throws Exception{
 Authentication authentication = new UsernamePasswordAuthenticationToken(new CustomUserDetails(..), null);
 SecurityContextHolder.getContext().setAuthentication(authentication);
  
 xmlConfigSetup("classpath:/META-INF/spring/webmvc-config.xml", "classpath:/org/bk/lmt/web/contextcontrollertest.xml").build()
  .perform(post("/contexts").param("name", "context1"))
  .andExpect(status().isOk())
  .andExpect(view().name("redirect:/contexts"));
}

Теперь тест стал намного более кратким, и нет необходимости напрямую иметь дело с экземплярами MockHttpServletRequest и MockHttpServletResponse, и он очень хорошо читает.

У меня есть небольшая оговорка относительно количества статического импорта и количества вызовов функций, которые здесь задействованы, но опять же, как и все остальное, это просто вопрос привыкания к этому подходу тестирования.

Ресурсы в разделе WEB-INF также можно использовать с spring-test-mvc, таким образом:

01
02
03
04
05
06
07
08
09
10
11
xmlConfigSetup("/WEB-INF/spring/webmvc-config.xml","classpath:/org/bk/lmt/web/contextcontrollertest.xml")
 .configureWebAppRootDir("src/main/webapp", false).build()
 .perform(post("/contexts").param("name", "context1"))
 .andExpect(status().isOk())
 .andExpect(view().name("redirect:/contexts"));
  
xmlConfigSetup("/WEB-INF/spring/webmvc-config.xml", "classpath:/org/bk/lmt/web/contextcontrollertest.xml")
 .configureWebAppRootDir("src/main/webapp", false).build()
 .perform(get("/contexts"))
 .andExpect(status().isOk())
 .andExpect(view().name("contexts/list"));

Ссылка: Spring MVC Integration Tests от нашего партнера JCG Биджу Кунджуммена в блоге all and sundry.