【问题标题】:Inject data into session from JUnit test从 JUnit 测试将数据注入会话
【发布时间】:2015-11-15 09:56:52
【问题描述】:

我需要运行 JUnit 与 Spring MVC 测试用例,其中的前提条件包括 HTTP Session 中存在某些数据。最重要的是我无法连接 session-scoped bean:我必须访问 httpServletContext.getSession()

在展示代码之前,让我解释一下。我需要测试的控制器假定某个数据存储在会话中,否则会引发异常。这是目前正确的行为,因为在没有会话的情况下永远不会调用该控制器,并且会话始终在登录时使用应用程序数据进行初始化。显然控制器处于安全状态。

在我的测试中,我只需要根据请求参数测试这个控制器是返回重定向还是404未找到。

我想构建我的测试用例,例如

@Autowired
private HttpServletRequest httpServletRequest;

@Autowired
private ModuleManager moduleManager;

@Autowired
private WebApplicationContext webApplicationContext;

private MenuItem rootMenu;

private MockMvc mockMvc;


@Before
public void setUp() throws Exception
{

    mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
                             // No asserzioni
                             .build();

    rootMenu = moduleManager.getRootMenu()
                            .clone();
    httpServletRequest.getSession()
                      .setAttribute(MenuItem.SESSION_KEY, rootMenu);

    assertNotNull(rootMenu.getDescendant(existingSelectedMenu));
    assertNull(rootMenu.getDescendant(notExistingMenu));

}

@Test
public void testNavigate() throws Exception
{

    mockMvc.perform(get("/common/navigate?target=" + existingSelectedMenu))
           .andExpect(status().is3xxRedirection());

    assertNotSelected(rootMenu, existingSelectedMenu);

    mockMvc.perform(get("/common/navigate?target=" + notExistingMenu))
           .andExpect(status().is4xxClientError());

}

部分代码是真正不言自明的。无论如何,我希望/common/navigate 使用我存储在会话中的值。像这样

@RequestMapping(value = "/common/navigate",
        method = RequestMethod.GET)
public String navigate(@RequestParam("target") String target) throws NotFoundException
{

    MenuItem rootMenu = (MenuItem) httpServletRequest.getSession()
                                               .getAttribute(MenuItem.SESSION_KEY);
    if (rootMenu == null)
        throw new RuntimeException("Menu not found in session"); //Never happens

    MenuItem menuItem = rootMenu.getAndSelect(target);
    if (menuItem == null)
        throw new NotFoundException(MenuItem.class, target); //Expected

    return "redirect:" + menuItem.getUrl();
}

现在猜一猜。当我运行我的代码时会发生什么?

RuntimeException 在我注释的行中抛出,因为在会话中找不到菜单对象

显然这个问题现在是隐含的,但我仍然会写它:如何将数据注入 Session 对象,以便被测控制器将它们作为前提条件可用?

【问题讨论】:

    标签: java spring-mvc session junit spring-mvc-test


    【解决方案1】:

    现在自己找到了解决办法。

    问题是会话本身也必须被模拟。 Spring 提供了一个 MockHttpSession 类来解决问题。它可以预先填充所有前置条件,必须传递给每个 MockMvc 请求,以便模拟将会话连接到(模拟的)servlet 上下文。

    以下代码初始化会话

        mockHttpSession = new MockHttpSession(webApplicationContext.getServletContext());
    
        mockHttpSession.setAttribute(MenuItem.SESSION_KEY, rootMenu);
    

    以下通过连接到它的模拟会话执行请求

    mockMvc.perform(get("/common/navigate?target=" + existingSelectedMenu).session(mockHttpSession))
               .andExpect(status().is3xxRedirection());
    

    【讨论】:

      猜你喜欢
      • 2018-05-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-08
      • 1970-01-01
      • 2019-05-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多