В веб-приложении на основе Spring bean-объекты могут быть привязаны к «сеансу» пользователя. По сути, это означает, что изменения состояния bean-объекта области видимости видны только в области сеанса пользователя.
Цель этой записи — просто выделить способ, предоставленный Spring Test MVC, для тестирования компонентов, которые имеют в качестве зависимостей бины сессионной области.
Рассмотрим пример из ссылочных документов Spring класса UserPreferences, в котором, скажем, указан timeZoneId пользователя:
01
02
03
04
05
06
07
08
09
10
11
|
@Component @Scope (value= "session" , proxyMode=ScopedProxyMode.TARGET_CLASS) public class UserPreferences { private String timeZoneId= "default" ; public String getTimeZoneId() { return timeZoneId; } public void setTimeZoneId(String timeZoneId) { this .timeZoneId = timeZoneId; } } |
Здесь область видимости помечена как «сессия», а proxyMode явно указан как TARGET_CLASS, чтобы инструктировать Spring для создания прокси CGLIB (поскольку UserPreferences не реализует какой-либо другой интерфейс).
Теперь рассмотрим контроллер, использующий этот bean-объект сессионной области в качестве зависимости:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
@Controller public class HomeController { @Autowired private UserPreferences userPreferences; @RequestMapping (value= "/setuserprefs" ) public String setUserPrefs( @RequestParam ( "timeZoneId" ) String timeZoneId, Model model) { userPreferences.setTimeZoneId(timeZoneId); model.addAttribute( "timeZone" , userPreferences.getTimeZoneId()); return "preferences" ; } @RequestMapping (value= "/gotopage" ) public String goToPage( @RequestParam ( "page" ) String page, Model model) { model.addAttribute( "timeZone" , userPreferences.getTimeZoneId()); return page; } } |
Здесь есть два метода контроллера, в первом методе пользовательское предпочтение установлено, и во втором методе пользовательское предпочтение прочитано. Если bean-объект в области сеанса работает чисто, то вызов «/ setuserprefs» в пользовательском сеансе должен установить предпочтение timeZoneId в bean-компоненте UserPreferences, а другой вызов «/ gotopage» в том же сеансе должен успешно извлечь ранее установленное предпочтение.
Проверить это просто с помощью поддержки тестирования Spring MVC, которая теперь поставляется с модулем Spring-test.
Тест выглядит примерно так:
Сначала определение bean-компонента для теста с использованием Spring Java Configuration:
1
2
3
4
|
@Configuration @EnableWebMvc @ComponentScan ({ "scope.model" , "scope.services" , "scope.web" }) public class ScopeConfiguration {} |
и тест:
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.mock.web.MockHttpSession; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; import org.springframework.web.context.WebApplicationContext; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*; @RunWith (SpringJUnit4ClassRunner. class ) @ContextConfiguration (classes=ScopeConfiguration. class ) @WebAppConfiguration public class ScopeConfigurationTest { @Autowired private WebApplicationContext wac; private MockMvc mockMvc; @Before public void setup() { this .mockMvc = webAppContextSetup( this .wac).build(); } @Test public void testSessionScope() throws Exception { MockHttpSession mocksession = new MockHttpSession(); this .mockMvc.perform( get( "/setuserprefs?timeZoneId={timeZoneId}" , "US/Pacific" ) .session(mocksession)) .andExpect(model().attribute( "timeZone" , "US/Pacific" )); this .mockMvc.perform( get( "/gotopage?page={page}" , "home" ) .session(mocksession)) .andExpect(model().attribute( "timeZone" , "US/Pacific" )); this .mockMvc.perform( get( "/gotopage?page={page}" , "home" ) .session( new MockHttpSession())) .andExpect(model().attribute( "timeZone" , "default" )); } } |
В тесте сначала создается MockHttpSession для имитации пользовательского сеанса. Последующие два запроса выполняются в контексте этого фиктивного сеанса, поэтому ожидается, что один и тот же компонент UserPreferences будет виден в контроллере, который утверждается в тесте. В третьем запросе создается новый сеанс, и на этот раз в контроллере виден другой бин UserPreferences, который утверждается поиском другого атрибута.
Это демонстрирует чистый способ тестирования bean-компонентов сессионной области с использованием поддержки Spring test MVC.