Статьи

Тестирование Spring «сессия» сфера

В веб-приложении на основе 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.

Ссылка: « Весенняя сессия» Testing от нашего партнера JCG Биджу Кунджуммена в блоге all and sundry.