【问题标题】:Partial Mocking on HttpSession对 HttpSession 的部分模拟
【发布时间】:2014-04-10 08:13:11
【问题描述】:

有一个我想测试的 servlet,servlet 有会话并将“loginBean”(包含登录用户相关信息)放入会话中,我已经模拟并且工作正常,现在在 GUI 级别,有 2 个选项卡, DetailSet1 , detailsS​​et2 ,当你输入 DetailSet1 的数据时,它会保存在 session 中,并且还会执行一些业务逻辑,现在谈到 DetailsS​​et2 ,你已经在 session 中有 DetailSet1 ,所以它得到了它所需要的一切,数据保存在 DB 中。现在很明显我必须模拟 HttpSession 因为我从容器外部运行单元案例,但是存储的数据也在 HttpSession 中,如果我也模拟这些,它就违背了测试的目的。所以我的问题是,我需要 HttpSession 对象来为我模拟它的对象返回模拟数据,并且假设在其他情况下它的行为就像任何普通的 HttpSession 对象一样。就像,如果代码是 session.setAttribute("name","Vivek") ,那么 session.getAttribute("name") 应该在那之后返回“Vivek”,但是如果是模拟对象,它返回“NULL”,为什么?因为我没有嘲笑“getAttribute("name") 的行为。

简而言之,对 HttpSession 或接口进行部分模拟。

【问题讨论】:

  • PS,我也尝试过 ServletUnit,但我不想根据返回的 HTML 进行测试,而且 JS 支持很差。我必须嘲笑它​​。许多应用程序使用 HttpSession 并在其中设置一些值并从其他控制器方法中读取它。我想说的是,对我来说,这似乎很常见,但很难得到答案,我之前没有做过 Junit 测试,但我得到了答案,我会在许多博客中发布解决方案。请帮忙。

标签: java unit-testing junit mockito


【解决方案1】:

HttpSession 是一个接口,因此您需要编写自己的实现或模拟它。我建议使用 Mockito 模拟它,然后将 getAttributesetAttribute 存根以委托给 HashMap 或其他一些合适的结构。

所以在您的测试类中,您将拥有

的字段
  • 你嘲笑的HttpSession
  • 真正的HashMap<String,Object>

您将为getAttributesetAttribute 中的每一个使用Answer<Object> 对象。每个Answer 只会将调用委托给HashMap

您可以在@Before 方法或@Test 这样的方法中设置所有这些。

@Mock private HttpSession mockHttpSession;
Map<String,Object> attributes = new HashMap<String,Object>();

@Test
public void theTestMethod() {

    Mockito.doAnswer(new Answer<Object>(){
        @Override
        public Object answer(InvocationOnMock invocation) throws Throwable {
            String key = (String) invocation.getArguments()[0];
            return attributes.get(key);
        }
    }).when(mockHttpSession).getAttribute(anyString());

    Mockito.doAnswer(new Answer<Object>(){
        @Override
        public Object answer(InvocationOnMock invocation) throws Throwable {
            String key = (String) invocation.getArguments()[0];
            Object value = invocation.getArguments()[1];
            attributes.put(key, value);
            return null;
        }
    }).when(mockHttpSession).setAttribute(anyString(), any());

【讨论】:

  • 我正在使用 Mockito,如果我创建自己的实现,我将不得不覆盖它的大部分方法,你现在能准确告诉我吗,大约 5 10 行代码。我会很开心的。
  • 谢谢,我会试试这个,我现在不关闭这个,如果我遇到任何麻烦会稍后回复。谢谢大卫:)
  • 嗨大卫,我遇到了另一个问题,Enumeration> names = request.getParameterNames(); ,我在此使用 Spring-mock 的 MockHttpServletRequest 使用了部分模拟,它不起作用,当在代码中调用 request.getParamterNames 时,我想返回我存根的参数的名称。有什么想法吗?
  • 所以你不能写一个Answer 对象,就像这里的两个,只是拉出地图的键集?
  • 是的,我做到了,必须更改答案中的所有存根代码,希望避免这种情况:P
【解决方案2】:

Spring Testing framework 包括 MockHttpSession。它可以通过 Maven 获得:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>4.0.1.RELEASE</version>
</dependency>

【讨论】:

  • 感谢 Paul,@David 的解决方案似乎也奏效了,但总是很高兴知道做一件事的更多方法,非常感谢 Paul :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-16
  • 1970-01-01
  • 2011-02-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多