【问题标题】:How to partially mock HttpServletRequest using Mockito如何使用 Mockito 部分模拟 HttpServletRequest
【发布时间】:2014-03-28 13:33:16
【问题描述】:

我正在模拟一个 HttpServletRequest ,在 servlet 调用中,请求中设置了新值,因为使用相同的请求我们将请求发送到某个 jsp,因此请求对象用作 servlet 的输入对象以及下一页的输出。

我模拟了所有输入参数,但是对于所有 request.setAttribute(),我的代码什么也没做,因为它是一个模拟类,如果我有

request.setAttribute(a,"10")
System.out.println("a = " + request.getAttribute("a"));

我得到 null 因为我没有对 Request.getAttribute("a") 给出任何行为,我不能,这是我对下一页的响应,所以解释我需要 2 行为我的请求对象因此部分模拟,到目前为止,我无法窥探或对其进行任何部分嘲笑。有什么想法吗?

代码:

 //Testcase
   Myservlet.java
public void doPost(request,response)
    {
         String a = request.getAttribute("a");
         String b = request.getAttribute("b");
         int sum = Integer.parseInt(a) + Integer.parseInt(b);
         request.setAttribute("sum",sum);
         //well in this example i can use sum what i calculated but in real senario i can't , i have to use request.getAttribute("sum")
         insertSumIntoDB(request.getAttribute("sum"));
    }
    }



  //testMyservlet.java
   @test
public void testServlet()
 {
 HttpServletRequest request = mock(HttpServletRequest.class);
     HttpServletResponse response = mock(HttpServletResponse.class);
when(request.getAttribute(a)).thenReturn("10");
when(request.getAttribute(b)).thenReturn("20");
new Myservlet(request,response);
}

【问题讨论】:

  • 你能展示你的嘲讽尝试吗?
  • 我又换了帖子。见 insertSumIntoDB(request.getAttribute("sum")) 这实际上是 insertSumintoDb(null) ,因为我没有给出 request.getAttribute("sum");

标签: java unit-testing mockito junit4


【解决方案1】:

Spring 的 MockHttpServletRequest 和 MockHttpServletResponse 可用于此目的。例如

    MockHttpServletRequest request = new MockHttpServletRequest();
    MockHttpServletResponse response = new MockHttpServletResponse();
    request.addHeader(HttpHeaders.HOST, "myhost.com");
    request.setLocalPort(PORT_VALID); // e.g. 8081
    request.setRemoteAddr(REQUEST_IP); // e.g. 127.0.0.1

然后我可以调用 myclass.method(request, response, ...) 并检查某些属性是否已正确设置到请求中,例如

    MyBean attr = (MyBean) request.getAttribute(ATTRIBUTE_NAME));
    // do my Assert.* stuff with 'attr'

MockHttpServletRequest 和 MockHttpServletResponse 在 mock(HttpServletRequest.class) 失败的情况下可以正常工作,例如,您需要取回之前在业务逻辑中设置的请求属性的真实内容。

【讨论】:

  • MockHttpServletRequest 和 MockHttpServletResponse 是 Spring 的一部分。如果您没有使用 Spring,那么您将无法使用它们。
  • @JimJarrett 你是对的;另一方面,包含 MockHttpServlet... 类的 spring-test 依赖项相当轻量级(只需要 spring-core),因此也许值得将其拉入测试范围以获得更好的测试。
【解决方案2】:

您需要将属性存储到集合中:

// Collection to store attributes keys/values
final Map<String, Object> attributes = new ConcurrentHashMap<String, Object>();     

// Mock setAttribute
Mockito.doAnswer(new Answer<Void>() {
    @Override
    public Void answer(InvocationOnMock invocation) throws Throwable {
        String key = invocation.getArgumentAt(0, String.class);
        Object value = invocation.getArgumentAt(1, Object.class);
        attributes.put(key, value);
        System.out.println("put attribute key="+key+", value="+value);
        return null;
    }
}).when(request).setAttribute(Mockito.anyString(), Mockito.anyObject());

// Mock getAttribute
Mockito.doAnswer(new Answer<Object>() {
    @Override
    public Object answer(InvocationOnMock invocation) throws Throwable {
        String key = invocation.getArgumentAt(0, String.class);
        Object value = attributes.get(key);
        System.out.println("get attribute value for key="+key+" : "+value);
        return value;
    }
}).when(request).getAttribute(Mockito.anyString());

【讨论】:

    【解决方案3】:

    Mockito 支持真正的部分模拟:Real partial mocks (Since 1.8.0)

    我认为它符合您的需求

    【讨论】:

    • 感谢您抽出宝贵时间,我无法窥探 HttpServletRequest ,它是一个接口。间谍在类上工作。
    • 抱歉,参考文献已损坏
    猜你喜欢
    • 2013-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-01
    相关资源
    最近更新 更多