【问题标题】:Manually setting header for testing手动设置标题以进行测试
【发布时间】:2011-11-05 10:10:00
【问题描述】:

我想创建一个 servlet 类,它从 jsp 接收两个输入参数,比如说 login.jsp 和 servlet“CommandQueueTestServlet”将这些传入参数设置为标头参数,然后将请求和响应参数发送到另一个 servlet“CheckForCommandServlet ”。

我需要这样做只是为了测试我的功能,因为我的“CheckForCommandServlet”实际上会被其他一些具有标头参数的应用程序调用。

但对于我自己的测试,我想创建一个 servlet“CommandQueueTestServlet”来设置标头。

请检查下面我要解释的代码

javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;

public class CommandQueueTestServlet extends HttpServlet{

 public void doGet(HttpServletRequest request,
         HttpServletResponse response)
throws ServletException, IOException {


String hwId=request.getParameter("hardware_id");
String panelistId=request.getParameter("panelist_id")); 

// Setting input parameter as header parameter.Since request object dont have setHeader so setting in response
//object

response.setHeader("x-HwId",hwid);
response.setHeader("x-panelistId,panelistId);

// creating instance of CheckForCommandServlet and passing in doGet() method:

CheckForCommandServlet headerParam= new CheckForCommandServlet();

 headerParam.doGet(request,response);


 }
 }

 // Code for CheckForCommandServlet 

 public class CheckForCommandServlet extends HttpServlet {

 @Override
 public void doGet(HttpServletRequest request, HttpServletResponse response)
 throws ServletException, IOException {



    Enumeration enumeration = httpServletRequest.getHeaderNames();
    String headerName;
    String headerValue;
    while (enumeration.hasMoreElements())
    {
        headerName = (String)enumeration.nextElement();
        if (headerName == null)
        {
            headerName = "";
        }

        headerName = headerName.toLowerCase();
        headerValue = httpServletRequest.getHeader(headerName);
        logger.log(Level.INFO, "Header headerName " + headerName);
        logger.log(Level.INFO, "Header ParamaterValue " + headerValue);

    }

  }

我的 CheckForCommandServlet 是如何获得在 CommandQueueTestServlet 中设置的 headerParemeter 的,因为它是在 header 参数中设置的。

【问题讨论】:

    标签: java servlets


    【解决方案1】:

    以下几行:

    // Setting input parameter as header parameter.Since request object dont have setHeader so setting in response
    //object
    
    response.setHeader("x-HwId",hwid);
    response.setHeader("x-panelistId,panelistId);
    

    将两个标头添加到将由 servlet 容器生成的 HTTP 响应,而不是转发到 CheckForCommandServlet servlet 的 HTTP 请求。

    由于您的意图是在原始请求中添加 HTTP 标头,以便随后的 HttpServletRequest.getHeader() 调用读取适当的值,您可以采用覆盖 getHeader 方法的 HttpServletRequestWrapper 的方法,以返回客户端发送的值。更多详情请见this related StackOverflow answer


    为了验证CheckForCommandServlet 的行为,更好的方法是使用像Fiddler 这样的HTTP 调试代理。 Fiddler 允许您将request headers automatically 添加到客户端发出的请求中。您需要做的就是确保将客户端配置为使用 Fiddler 作为 HTTP 代理。

    即使您的意图是编写轻量级单元测试,最好在客户端中使用像 Apache HttpComponents 这样的 HTTP 库,而不是涉及编写请求包装器和 servlet 的方法需要构建特定于测试的 WAR 的开销。

    【讨论】:

      【解决方案2】:

      为了扩展 Vineet Reynolds 的出色回答,这是一种使用 java.net.HttpURLConnection 设置 HTTP 标头的方法:

      URL url = new URL("http://localhost:8080/CheckForCommandServlet");
      HttpURLConnection connection = (HttpURLConnection)url.openConnection();
      connection.setRequestProperty("X-HwId", "Foo");
      connection.setRequestProperty("X-panelistId", "Bar");
      connection.setRequestMethod("GET");
      connection.connect();
      connection.getInputStream().close(); //Must open stream to make request.
      connection.disconnect();
      

      你可以在你的功能测试中总结出这样的东西来断言响应等等。


      编辑

      使用HttpServletRequestWrapper

      1. 将标头设置为请求属性。
      2. 在您的包装器中覆盖 getHeader(String name)getHeaderNames()
      3. 使用包装器代替请求转发到目标 servlet。

      代码(请注意,为简洁起见,我删除了导入):

      public class CommandQueueTestServlet extends HttpServlet {
          private static final long serialVersionUID = 1L;
      
          protected void doGet(HttpServletRequest request,
                  HttpServletResponse response) throws ServletException, IOException {
              MyWrapper wrapper = new MyWrapper(request);
              request.setAttribute("X-HwId", "HardWare ID");
              request.setAttribute("X-PanelListId", "Panel List ID");
              request.getRequestDispatcher("/CheckForCommandServlet").forward(
                      wrapper, response);
          }
      
          private static class MyWrapper extends HttpServletRequestWrapper {
      
              public MyWrapper(HttpServletRequest request) {
                  super(request);
              }
      
              @Override
              public String getHeader(String name) {
                  String header = super.getHeader(name);
                  return header == null ? (String) super.getAttribute(name) : header;
              }
      
              @Override
              @SuppressWarnings("unchecked")
              public Enumeration<String> getHeaderNames() {
                  List<String> headerNames = Collections.list(super.getHeaderNames());
                  headerNames.addAll(Collections.list(super.getAttributeNames()));
                  return Collections.enumeration(headerNames);
              }
          }
      }
      

      您现在应该可以像往常一样使用request.getHeader(String name)了:

      public class CheckForCommandServlet extends HttpServlet {
          private static final long serialVersionUID = 1L;
      
          protected void doGet(HttpServletRequest request,
                  HttpServletResponse response) throws ServletException, IOException {
              response.getWriter()
                      .format("Hardware ID = %s\n Panel List ID = %s",
                              request.getHeader("X-HwId"),
                              request.getHeader("X-PanelListId"));
          }
      }
      

      尽管这可行,但它是一个相当脆弱的测试,正如 Vineet 已经提到的,它需要您部署一个单独的 WAR。恕我直言,在某种测试中使用 servlet 代码之外的 HTTP 库仍然是最好的方法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-23
        • 2014-11-03
        • 1970-01-01
        • 2010-10-10
        • 2011-04-10
        • 2011-03-11
        相关资源
        最近更新 更多