В продолжение моих предыдущих блогов, посвященных знакомству со Spring MVC и слою службы тестирования в Spring MVC , в этом блоге я продемонстрирую, как тестировать контроллер в Spring MVC . Целью этой демонстрации является двухкратное построение уровня контроллера с использованием TDD и увеличение покрытия кода во время JUnit-тестирования контроллера.
Если вы спешите, получите последний код от Github и выполните команду ниже
mvn clean test -Dtest=com.example.bookstore.web.controller.SpringMvcTestLoginControllerTest
Поскольку в моем предыдущем блоге мы уже протестировали и внедрили уровень обслуживания, в этом блоге нам нужно сосредоточиться только на тестировании контроллера. Для тестирования контроллера я буду использовать фреймворк Spring-Test-MVC , который я достаточно обсуждал в своих предыдущих блогах. Spring-test-MVC реализует домен-специфический язык (DSL) для тестирования контроллера.
В качестве первого шага мы определяем класс LoginControllerTestConfiguration с помощью класса LoginControllerTest. Если вы заметили, что в этом классе определены 2 bean-компонента, и мы пометили его как @Configuration, который показывает, что это класс Spring Context. В тесте JUnit мы использовали класс @Autowired LoginController и класс @Autowired AccountService. При создании Бина в файле конфигурации мы также пометили класс AccountService с помощью Mockito ,
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration public class SpringMvcTestLoginControllerTest { @Configuration static class LoginControllerTestConfiguration { @Bean public AccountService accountService() { return Mockito.mock(AccountService.class); } @Bean public LoginController loginController() { return new LoginController(); } } @Autowired private LoginController loginController; @Autowired private AccountService accountService; }
В качестве следующего шага давайте настроим данные. Если вы заметили приведенный ниже код, мы также отключили метод входа в AccountService для возврата предварительно сконфигурированных данных с использованием Mockito .
@Before public void setup() throws Exception { this.account = new AccountBuilder() { { address("Herve", "4650", "Rue de la station", "1", null, "Belgium"); credentials("john", "secret"); name("John", "Doe"); } }.build(true); Mockito.when(this.accountService.login("john", "secret")).thenReturn(this.account); }
Затем мы пишем тест, в котором мы устанавливаем loginController в MockMvcBuilders и используем DSL Spring-test-MVC для вызова уровня контроллера и выполнения утверждений. Теперь, если вы запустите тест, он пройдет успешно.
@Test public void testHandleLogin() throws Exception { MockMvc mockMvc = MockMvcBuilders.standaloneSetup(this.loginController).build(); mockMvc.perform(post("/login").param("username", "john").param("password", "secret")) .andExpect(status().isOk()) .andExpect(request().sessionAttribute(LoginController.ACCOUNT_ATTRIBUTE, this.account)) .andExpect(redirectedUrl("/index.htm")); }
Наконец, loginController выглядит следующим образом:
@Controller @RequestMapping(value = "/login") public class LoginController { @Autowired private AccountService accountService; @RequestMapping(method = RequestMethod.POST) public String handleLogin(@RequestParam String username, @RequestParam String password, HttpSession session) throws AuthenticationException { Account account = this.accountService.login(username, password); session.setAttribute(ACCOUNT_ATTRIBUTE, account); String url = (String) session.getAttribute(REQUESTED_URL); session.removeAttribute(REQUESTED_URL); // Remove the attribute if (StringUtils.hasText(url) && !url.contains("login")) { // Prevent loops for the login page. return "redirect:" + url; } else { return "redirect:/index.htm"; } } }
Я надеюсь, что этот блог помог вам. В моем следующем блоге мы будем реализовывать веб-слой.