在使用 httpclient 做接口相关测试的过程中,遇到过一个障碍:如何处理多用户同时登陆。之前用户身份凭证一般都是做公参里面处理或者在 header 中单独定义一个或者几个字段,cookie 都是使用 httpclient 自带的管理器自动管理的。
后来用户凭证存到了 cookie 里,这里就有了一些障碍,经过翻看资料得到了解决。

首先取消 cookie 的自动管理

设置如下:

/**
 * 获取请求超时控制器
 * <p>
 * cookieSpec:即cookie策略。参数为cookiespecs的一些字段。作用:
 * 1、如果网站header中有set-cookie字段时,采用默认方式可能会被cookie reject,无法写入cookie。将此属性设置成CookieSpecs.STANDARD_STRICT可避免此情况。
 * 2、如果要想忽略cookie访问,则将此属性设置成CookieSpecs.IGNORE_COOKIES。
 * </p>
 *
 * @return
 */
private static RequestConfig getRequestConfig() {
    return RequestConfig.custom().setConnectionRequestTimeout(HttpClientConstant.CONNECT_REQUEST_TIMEOUT).setConnectTimeout(HttpClientConstant.CONNECT_TIMEOUT).setSocketTimeout(HttpClientConstant.SOCKET_TIMEOUT).setCookieSpec(CookieSpecs.IGNORE_COOKIES).setRedirectsEnabled(false).build();
}

这里说明一点,这个 requestconfig 既可以在对 HTTPrequestbase 进行设置,也可以对 CloseableHttpClient 进行设置,由于在各个项目中都采取了单独处理 cookie 的设置,所以我是直接放在了连接池 CloseableHttpClient 对象的设置里面,如下:

    /**
     * 通过连接池获取https协议请求对象
     * <p>
     * 此处会默认添加一天defaultcookiesstore,会处理响应头中的set-cookie字段
     * 增加默认的请求控制器
     * </p>
     *
     * @return
     */
    private static CloseableHttpClient getCloseableHttpsClients() {
        // 创建自定义的httpsclient对象
        CloseableHttpClient client = HttpClients.custom().setConnectionManager(connManager).setRetryHandler(httpRequestRetryHandler).setDefaultRequestConfig(requestConfig).build();
//         CloseableHttpClient client = HttpClients.createDefault();//非连接池创建
        return client;
    }

其次处理 set-cookie 信息

我的方案是在处理响应的时候,只用 closeablehttpresponse 对象接收响应的,然后在单独在 header 里面遍历 set-cookie 字段的值,在处理 json 对象作为返回体的时候添加进去,如下:

/**
 * 响应结束之后,处理响应头信息,如set-cookien内容
 *
 * @param response 响应内容
 * @return
 */
private static JSONObject afterResponse(CloseableHttpResponse response) {
    JSONObject cookies = new JSONObject();
    List<Header> headers = Arrays.asList(response.getHeaders("Set-Cookie"));
    if (headers.size() == 0) return cookies;
    headers.forEach(x -> {
        String[] split = x.getValue().split(";")[0].split("=", 2);
        cookies.put(split[0], split[1]);
    });
    return cookies;
}


/**
 * 根据解析好的content,转化json对象
 *
 * @param content
 * @return
 */
private static JSONObject getJsonResponse(String content, JSONObject cookies) {
    JSONObject jsonObject = new JSONObject();
    try {
        jsonObject = JSONObject.fromObject(content);
    } catch (Exception e) {
        jsonObject.put("content", content);
        jsonObject.put("code", TEST_ERROR_CODE);
        logger.warn("响应体非json格式,已经自动转换成json格式!");
    } finally {
        if (!cookies.isEmpty()) jsonObject.put(HttpClientConstant.COOKIE, cookies);
        return jsonObject;
    }
}

最后处理多用户保存和携带 cookie

在每个项目的 base 对象接收到响应之后存储 cookie 以便子类继承,在每次发送请求的时候带上当前对象的 cookie,以对象形式存储每一个用户,达到多用户同时登录的目的,如下:

@Override
public JSONObject getResponse(HttpRequestBase httpRequestBase) {
    setHeaders(httpRequestBase);
    JSONObject response = FanLibrary.getHttpResponse(httpRequestBase);
    handleResponseHeader(response);
    return response;
}

@Override
public void setHeaders(HttpRequestBase httpRequestBase) {
    httpRequestBase.addHeader(Common.REQUEST_ID);
    httpRequestBase.addHeader(FanLibrary.getHeader("token", token));
    if (!cookies.isEmpty()) httpRequestBase.addHeader(FanLibrary.getCookies(cookies));
}

@Override
public void handleResponseHeader(JSONObject response) {
    if (!response.containsKey(HttpClientConstant.COOKIE)) return;
    cookies.putAll(response.getJSONObject(HttpClientConstant.COOKIE));
    response.remove(HttpClientConstant.COOKIE);
}

往期文章精选

  1. java 一行代码打印心形
  2. Linux 性能监控软件 netdata 中文汉化版
  3. 接口测试代码覆盖率(jacoco)方案分享
  4. 性能测试框架
  5. 如何在 Linux 命令行界面愉快进行性能测试
  6. 图解 HTTP 脑图
  7. 写给所有人的编程思维
  8. 测试之 JVM 命令脑图
  9. 将 json 数据格式化输出到控制台
  10. 如何测试概率型业务接口
  11. “双花” BUG 的测试分享
  12. 将 swagger 文档自动变成测试代码
  13. Mac+httpclient 高并发配置实例
  14. httpclient 处理多用户同时在线


↙↙↙阅读原文可查看相关链接,并与作者交流