http接口测试总结

1、使用HttpClient发送Get/Post请求
a)Get请求
代码示例:

	public static String getHttpResponse4Get() { 		
		CloseableHttpClient httpclient = HttpClients.createDefault();
		String url = "http://www.tmall.com/test.do?id=123";
		GetMethod httpGet = new GetMethod(url);
		httpGet.addRequestHeader("content-type", "text/html; charset=gbk");
		httpGet.getParams().setParameter("http.socket.timeout", 20000);
		try {
			// 设置成了默认的恢复策略,在发生异常时候将自动重试3次,在这里你也可以设置成自定义的恢复策略
			httpGet.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,new DefaultHttpMethodRetryHandler());
			if (httpclient.executeMethod(httpGet) != HttpStatus.SC_OK) {
				System.out.println("httpGet(\"" + url + "\") failed: \n"+ httpGet.getStatusLine());
				return null;
				}
			return httpGet.getResponseBodyAsString();
			} catch (Exception e) {
				System.out.println("httpGet(\"" + url + "\") failed: \n" + e.getMessage());
				return null;
			} finally {
			httpGet.releaseConnection();
			httpclient = null;
			}
		}


注意点:
1、传入参数值(或者参数串)需要进行encode,虽然httpClient中是有用URLCodec.encodeUrl()进行encode,但我实验发现,和URLEncoder.encode()进行encode的结果还是有区别,会对最终响应有影响,所以建议自行encode;
2、需要判断请求返回的状态码是否为200以后获取到的响应才是可靠的;
3、最终要释放掉链接,做好收尾工作。

b)Post请求
代码示例:

public static String getHttpResponse4Post() {
		try {
			HttpClient client = new DefaultHttpClient();
			HttpPost request = new HttpPost("http://www.tmall.com/test.do");
			// 使用NameValuePair来保存要传递的Post参数
			List postParameters = new ArrayList();
			// 添加要传递的参数
			postParameters.add(new BasicNameValuePair("id", "12345"));
			postParameters.add(new BasicNameValuePair("username", "dave"));
			// 实例化UrlEncodedFormEntity对象
			UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(
					postParameters);
			// 使用HttpPost对象来设置UrlEncodedFormEntity的Entity
			request.setEntity(formEntity);
			HttpResponse response = client.execute(request);
			if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				String s = EntityUtils.toString(response.getEntity(), "utf-8");
				System.out.println(s);
				System.out.println("请求正常,结束http请求");
				return s;
			}
		} catch (Exception e) {
			System.out.println("请求发生异常,异常信息抛出");
			e.printStackTrace();
		} finally {
			httpClient.getConnectionManager().shutdown();
		}
		return " ";
	}


c)在线上环境发送get请求
要将在daily下运行的http接口测试脚本放到线上运行,需要做如下一些操作:
1、建立一个真实的登录session:发送post请求到:https://login.taobao.com/member/login.jhtml
2、然后发送get请求到http://i.taobao.com/my_taobao.htm从缓存中同步一次cookie
3、通过this.httpClientLogin.getState().getCookies();获取到cookie信息,然后解析到_tb_token_的值
4、把这个_tb_token_这个参数和值附加到测试请求的url中,通过get方式进行请求即可
5、注意:在登录的post参数设置时,需要将字符集设为:GBK

postMethod.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "GBK"); 

如果改为utf-8或者不set此param就可能导致获取的cookie值不足的问题
(本部分感谢浣碧同学的悉心指点!)

2、urlencode/urldecode
为什么url需要encode以后才能发送,是因为URL需要转化为ASCII字符集才能在被HTTP协议使用。ASCII字符集7位的字符集,包含128个字符,其中常见的有数字1-9,还有a-zA-Z以及一些特殊字符。当URL中包含非ASCII字符集的字符的时候,就需要encode为ASCII字符集,以便通过HTTP协议发送请求
Java中进行URL Encode和Decode的方法是:

URLEncoder.encode(valueOfUrlParam, "UTF-8");   
URLDecoder.decode(urlParamStr, "UTF-8"); 

两个类都来自java.net的包,平时可以使用online的encode/decode网站进行操作
这里需要注意的是:
只能对URL的参数进行encode(可以把整个参数串进行encode,也可以只对参数值进行encode,不能对域名和URI进行encode,例如:
http://www.tmall.com/test.do?id=123,234,正确的encode以后的url为:
http://www.tmall.com/test.do?id%3d123%2c234 或者:
http://www.tmall.com/test.do?id=123%2c234
在用post发请求的时候,需要将参数内容组装成HttpEntity然后set到post对象中,此时会用到UrlEncodedFormEntity这个类,这类的构造函数里会把post的参数进行一次encode,所以自己不需要额外进行一次encode,否则应用服务器在一次decode情况下就会读取错误的参数值

3、mock
a) 参数mock
问题场景:在服务端应用程序里通常会有这样的片段:

	public static Long getLoginUserId(TurbineRunData rundata) {
		String userId = (String) rundata.getRequest().getSession()
				.getAttribute(SessionKeeper.ATTRIBUTE_USER_ID_NUM);
		if (StringUtils.isNumeric(userId)) {
			return Long.parseLong(userId);
		}
		return null;
	}


 

	if (userId==null || userId <= 0) {
		result.setSuccess(false);
		result.setErrorCode(MallBrandResultCode.USER_NOT_LOGIN);
		result.setErrorMsg("参数user_id缺失");
		}


如果webx不能从session中获取到userID,那就会被业务逻辑控制住,不能继续往下走,解决办法有两个:
l.往session里塞userId
要实现这种方案,首先需要创建一个真实daily下用户登录的session,由于是在daily下,还需要解决安全认证的问题,这样便能解决这个问题。但明显这样做的成本太高,而且不是很必要。
l通过get参数mock掉这段代码逻辑
和开发约定一个参数和参数值,在程序中判断如果有这个参数值则直接返回一个指定的userId。

b)压缩mock
为了防止前端发送的json数据时http的get请求超长,前后端开发通过7zip进行压缩,但httpClient认为这样的压缩过的请求是BadRequest,所以只能试图把请求换成post,同时把解压缩的逻辑mock掉,以便于daily下的接口测试。具体详见:《http接口测试中有关URL长度限制的问题(Maximum URL Length)》
c)csrf控制mock
代码中为了防止csrf攻击,都会加入csrf的控制模块,在daily下可以直接让开发把这段逻辑注释掉,但如果脚本还要在系统上线后回归,那就需要和开发一起把这段逻辑mock掉,以简化测试应用的复杂度,降低测试脚本开发难度。

 

你可能感兴趣的:(HttpClient,接口测试)