jetty模拟服务端作为测试桩进行接口测试详细介绍
2016-08-19 09:41
573 查看
有时,在进行接口测试时,很多时候需要依赖外部的接口环境,但在实际开发中,尤其是敏捷开发模式中,很多时候依赖的外部接口环境可能不通或者未开发完毕,这时候无法及时进行端到端的测试,测试桩的必要性就非常重要了。
我在上一篇文章中已介绍使用第三方工具SoapUI做为模拟服务端作为测试桩进行接口测试,详见http://blog.csdn.net/russ44/article/details/52230355
一、测试桩项目介
Jetty 设计的基本原则,详情可百度之
所需jar包(本人):
2.在servlet中处理请求,返回报文(测试桩主要目的是模拟接口,返回报文。请求处理啥的就掠过啦~)
<1> 处理xml格式响应报文,coding如下:
<2> 处理json格式响应报文,coding如下:
重要说明:
<1> 文件存放位置如下:
<2> xml文件转化为String的代码如下:
<3> json文件转换String代码如下:
<4> 输出响应报文代码如下:
3.测试桩运行。以HttpServerDemo为例,启动HttpServerDemo.java的main方法,浏览器中输入main方法中配置的请求路径http://localhost:19993/test/ChannelFaqSearch(我本机跑,ip为localhost,布置到服务器,换成服务器ip),就可以看到返回的报文了。
4.注意点
在服务器上打包运行,打包时注意main函数的选取(选自己写的要启动的端口对应的java类)。
以eclipse打jar包为例,步骤如下:
右键选中测试桩工程 --> export -->
点击next
点击finish完成
然后将打好的jar包(如jettyServer.jar)上传至服务器
即可命令运行jar包(先给jar文件赋权限,否者可能无法执行)。
例:命令如下:java -jar jettyServer.jar
2>.在配置文件中修改接口地址为对应的测试桩的地址(ip为jar包所在服务的主机ip,端口为定义的端口)
3>.将jar包部署到服务器(我目前在192.168.129.145服务器上建立了一个目录作为测试桩的存放路径:/apps/stub_test/大家可以统一将jar包放置此处,当然也可以自定义)
1>.#java -jar testStub.jar &
//该命令表示启动jar包
//注:加&表示将进程放置在后台运行
2>.#jobs
//查看后台运行的任务列表
3>.#nohup java -jar testStub.jar &
//如果想在退出终端后服务不终止则使用nohup命令,nohup的作用是即使退出终端,程序仍不会结束,使用nohup命令应注意该服务不会停止,不用时应注意将该进程kill
掉
//若出现下面提示信息,不是报错,它表示程序运行信息会输出到nohup.out
#nohup: ignoring input and appending output to `nohup.out'
4>.#jobs -l
如图所示,显示该服务的进程号
#kill -9 进程号
//干掉进程
2>.如果在启动jar包时报错,注意是否是端口号被占用
#知识传送门:
https://github.com/russ44/easyMock
以上是我写的用于测试桩的mock平台,非常简单易懂,直接将项目打成war包部署tomcat容器即可运行。
该平台通过前台web页面管理接口,可作为轻量级的mock平台
我在上一篇文章中已介绍使用第三方工具SoapUI做为模拟服务端作为测试桩进行接口测试,详见http://blog.csdn.net/russ44/article/details/52230355
但由于SoapUI通常部署在本地的Windows环境上(linux环境本人未使用过,不建议),而测试环境通常部署在linux服务器上,可能存在测试环境无法调通本地环境的情况,这时就需要另一种方式部署到linux服务器进行接口测试,详细如下:
一、测试桩项目介
绍
1. jetty介绍:
Jetty 是一个开源的servlet容器,它为基于Java的web容器,易用性是Jetty 设计的基本原则,详情可百度之
所需jar包(本人):
2. 测试桩目的:
测试人员在测试中,尤其是进行接口测试时,经常需要使用到测试桩来进行测试,通常情况下,相应的开发人员会写好相应的测试桩,以jar包的形式作为一个服务端给客户端进行调用(当接口联调未能按计划进行或延迟时,测试人员应主导向开发人员要求提供测试桩进行测试,具体视实际情况而定)3. 测试桩原理
相当于启动一个jetty容器,拦截对应的请求,返回相应的报文。4. 测试桩使用过程
1.在server包下写一个带main函数(这个main函数会启动一个jetty容器)的java类,配置端口号,想要拦截的请求,和对应的处理请求的servlet<span style="font-size:18px;">package cn.migu.server; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import cn.migu.servlet.JsonResponseDemo; import cn.migu.servlet.XmlResponseDemo; import cn.migu.util.Log4jUtil; /** * <Description> 服务入口配置 * @author YanLu * */ public class HttpServerDemo { //private static Log4jUtil log = new Log4jUtil(HttpServerDemo.class.getName()); /** * main方法入口 * * @param args */ public static void main(String[] args) { try { Server server = new Server(19993); // 指定服务的端口号 ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); // 一个context就是一个WEB-Application context.setContextPath("/test"); // 访问项目名(路径) server.setHandler(context); // servlet映射的路径,类似于web.xml的servlet url-pattern定义 context.addServlet(new ServletHolder(new XmlResponseDemo()), "/ChannelFaqSearch"); // 两个参数分别为拦截请求的servlet和想要拦截的路径 context.addServlet(new ServletHolder(new JsonResponseDemo()), "/ExecuteCampaign"); //log.info("server start."); System.out.println("server start."); // 启动服务 server.start(); server.join(); } catch (Exception e) { e.printStackTrace(); } } } </span>
2.在servlet中处理请求,返回报文(测试桩主要目的是模拟接口,返回报文。请求处理啥的就掠过啦~)
<1> 处理xml格式响应报文,coding如下:
<span style="font-size:18px;">package cn.migu.servlet; import java.io.IOException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import cn.migu.util.ConfigUtil; import cn.migu.util.GlobalSettings; import cn.migu.util.Log4jUtil; import cn.migu.util.OutPrinterUtil; import cn.migu.util.XMLReaderHelper; /** * <Description> 拦截执行活动请求,返回xml格式报文 * @author YanLu * */ public class XmlResponseDemo extends HttpServlet { //private Log4jUtil log = new Log4jUtil(this.getClass().getName()); @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { StringBuilder builder; //String filePath = "/apps/stub_test/responseProfile/ChannelFaqSearch.xml"; //String filePath = GlobalSettings.getProperty("ChannelFaqSearch"); //读取外部的xml文件 String filePath = ConfigUtil.CONFIG.get("ChannelFaqSearch"); //将xml文件转化为String String xmlStr = XMLReaderHelper.xmlStrReader(filePath); if (!(null == xmlStr)) { System.out.println("读取XML成功!"); builder = new StringBuilder(xmlStr); } else { System.out.println("读取XML失败!"); builder = new StringBuilder(1024); bindBuilder(builder); } //响应xml格式字符串 OutPrinterUtil.outputXml(response, builder); } @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { //同doPost方法 doPost(request, response); } private void bindBuilder(StringBuilder builder) { builder.append("<?xml version=\"1.0\" encoding=\"utf-8\"?><notifyRsp>"); builder.append("<transId>" + "cs112233" + "</transId>"); builder.append("<processTime>" + "230ms" + "</processTime>"); builder.append("<cpId>710302</cpId>"); builder.append("<bulletinType>1</bulletinType>"); builder.append("<bulletinID>1</bulletinID>"); builder.append("<bulletinID>1</bulletinID>"); builder.append("<returnCode>0000</returnCode>"); builder.append("<bulletinTitle>停电公告</bulletinTitle>"); builder.append("<bulletinCont>十月31号停电</bulletinCont>"); builder.append("<publishTime>20151021101212</publishTime>"); builder.append("<publishType>0</publishType>"); builder.append("<bulletinLevel>0</bulletinLevel>"); builder.append("<contactType>1</contactType>"); builder.append("<needReply>1</needReply>"); builder.append("<adminName> 管理员 </adminName >"); builder.append("<bulletinAttachs>"); builder.append("<bulletinAttach>"); builder.append("<attachName> 附件1 </attachName >"); builder.append("<attachType> 1 </attachType >"); builder.append("<attachURL> ftp://192.168.1.1/test.doc</attachURL>"); builder.append("</bulletinAttach>"); builder.append("<bulletinAttach>"); builder.append("<attachName> 附件2 </attachName >"); builder.append("<attachType> 2 </attachType >"); builder.append("<attachURL > ftp://192.168.1.1/test2.doc</attachURL>"); builder.append("</bulletinAttach >"); builder.append("</bulletinAttachs >"); builder.append("<replys >"); builder.append("<reply >"); builder.append("<replyTime > 20151011121212 </replyTime >"); builder.append("<replyType > 1 </replyType >"); builder.append("<replyCont > CP回复测试1 </replyCont >"); builder.append("<replyAttchs >"); builder.append("<replyAttch >"); builder.append("<attachName > 附件1 </attachName >"); builder.append("<attachURL > ftp://192.168.1.1/test.doc</attachURL>"); builder.append("</replyAttch >"); builder.append("</replyAttchs >"); builder.append("</reply >"); builder.append("<reply >"); builder.append("<replyTime > 20151011121212 </replyTime >"); builder.append("<replyType > 2 </replyType >"); builder.append("<replyCont > 管理员回复测试1 </replyCont >"); builder.append("<replyAttchs >"); builder.append("<replyAttch >"); builder.append("<attachName > 附件1 </attachName >"); builder.append("<attachURL > ftp://192.168.1.1/test.doc</attachURL>"); builder.append("</replyAttch >"); builder.append("</replyAttchs >"); builder.append("</reply >"); builder.append("</replys >"); builder.append("</notifyRsp>"); } } </span>
<2> 处理json格式响应报文,coding如下:
<span style="font-size:18px;">package cn.migu.servlet; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import cn.migu.util.ConfigUtil; import cn.migu.util.FileUtil; import cn.migu.util.GlobalSettings; import cn.migu.util.OutPrinterUtil; import java.io.IOException; /** * <Description> 拦截执行活动请求,返回json格式报文 * @author YanLu * */ public class JsonResponseDemo extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //String filePath = "/apps/stub_test/responseProfile/ExecuteCampaign.json"; String filePath = ConfigUtil.CONFIG.get("ExecuteCampaign"); //将json文件转化为String String resultJson= FileUtil.ReadFile(filePath); //响应json格式字符串 OutPrinterUtil.outputJson(resultJson, resp); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } } </span>
重要说明:
<1> 文件存放位置如下:
<span style="font-size:18px;">#配置文件路径 #文件置于当前工程的profile目录下 #ChannelFaqSearch=./profile/ChannelFaqSearch.xml #ExecuteCampaign=./profile/ExecuteCampaign.json #文件置于与项目同级的目录下 ChannelFaqSearch=./responseProfile/ChannelFaqSearch.xml ExecuteCampaign=./responseProfile/ExecuteCampaign.json #文件路径为按绝对路径 #ChannelFaqSearch=/apps/responseProfile/ChannelFaqSearch.xml</span>
<2> xml文件转化为String的代码如下:
<span style="font-size:18px;">package cn.migu.util; import org.w3c.dom.Document; import org.xml.sax.SAXException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.*; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import java.io.ByteArrayOutputStream; import java.io.IOException; /** * <Description> XMLReader帮助类 * @author YanLu * */ public class XMLReaderHelper { private static Document document; //将xml文件转换为String,使用dom方式解析xml public static String xmlStrReader(String fileName) { try { //获取DOM解析器工厂,以便生产解析器 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); //获取DOM解析器,以便解析DOM DocumentBuilder db = dbf.newDocumentBuilder(); //把要解析的 XML 文档转化为输入流,以便 DOM 解析器解析它 //InputStream is= new FileInputStream("test1.xml"); //解析 XML 文档的输入流,得到一个 Document document = db.parse(fileName); TransformerFactory tf = TransformerFactory.newInstance(); Transformer t = tf.newTransformer(); t.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); ByteArrayOutputStream bos = new ByteArrayOutputStream(); t.transform(new DOMSource(document), new StreamResult(bos)); String xmlStr = bos.toString(); return xmlStr; } catch (ParserConfigurationException e) { System.err.println(e.getMessage()); } catch (SAXException e) { System.err.println(e.getMessage()); } catch (IOException e) { System.err.println(e.getMessage()); } catch (TransformerConfigurationException e) { System.err.println(e.getMessage()); } catch (TransformerException e) { System.err.println(e.getMessage()); } return null; } } </span>
<3> json文件转换String代码如下:
<span style="font-size:18px;">package cn.migu.util; import java.io.*; /** * <Description> 读取文件方法封装 * @author YanLu * */ public class FileUtil { /** * 读取.json文件方法 * @param filePath * @return */ public static String ReadFile(String filePath) { BufferedReader reader=null; StringBuilder result=null; try { FileInputStream inStream=new FileInputStream(filePath); InputStreamReader inReader=new InputStreamReader(inStream,"UTF-8"); reader=new BufferedReader(inReader); result=new StringBuilder(); String tempStr; while((tempStr=reader.readLine())!=null){ result.append(tempStr); } reader.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { if(reader!=null) { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } } return result.toString(); } } </span>
<4> 输出响应报文代码如下:
<span style="font-size:18px;">package cn.migu.util; import org.eclipse.jetty.server.Request; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.http.HttpServletResponse; /** * <Description> 响应输出流工具类示例,可自行定制 * * @author YanLu * */ public class OutPrinterUtil { /** * 响应xml格式字符串 * * @param response * @param result * @throws IOException */ public static void outputXml(HttpServletResponse response, StringBuilder result) throws IOException { // response.setContentType("application/xml"); response.setCharacterEncoding("UTF-8"); response.setStatus(HttpServletResponse.SC_OK); System.err.println("响应码为:"+HttpServletResponse.SC_OK); PrintWriter pw = response.getWriter(); pw.print(result.toString()); pw.flush(); pw.close(); } /** * 响应json格式字符串 * * @param json * @param response */ public static void outputJson(String json, HttpServletResponse response) { try { response.setCharacterEncoding("UTF-8"); // json串必须要是json格式,否则会出错 response.setContentType("application/json"); //在代理服务器端防止缓冲 response.setDateHeader("Expires", 0); PrintWriter out = response.getWriter(); out.print(json); out.flush(); out.close(); } catch (Exception e) { e.printStackTrace(); } } /** * 需要返回给用户的结果不支持session * * @param baseRequest * @param response * @param result * @throws IOException */ public static void outputNoSession(Request baseRequest, HttpServletResponse response, String result) throws IOException { response.setContentType("text/json;charset=utf-8"); response.setStatus(HttpServletResponse.SC_OK); baseRequest.setHandled(true); response.getWriter().println(result); } /* * private OutPrinterUtil() { super(); } */ } </span>
3.测试桩运行。以HttpServerDemo为例,启动HttpServerDemo.java的main方法,浏览器中输入main方法中配置的请求路径http://localhost:19993/test/ChannelFaqSearch(我本机跑,ip为localhost,布置到服务器,换成服务器ip),就可以看到返回的报文了。
4.注意点
在服务器上打包运行,打包时注意main函数的选取(选自己写的要启动的端口对应的java类)。
以eclipse打jar包为例,步骤如下:
右键选中测试桩工程 --> export -->
点击next
点击finish完成
然后将打好的jar包(如jettyServer.jar)上传至服务器
即可命令运行jar包(先给jar文件赋权限,否者可能无法执行)。
例:命令如下:java -jar jettyServer.jar
二、测试桩服务器部署
1 部署测试桩环境
1>.测试桩完成后打为jar包,需确认包中定义的相关端口号,及测试桩的请求路径。2>.在配置文件中修改接口地址为对应的测试桩的地址(ip为jar包所在服务的主机ip,端口为定义的端口)
3>.将jar包部署到服务器(我目前在192.168.129.145服务器上建立了一个目录作为测试桩的存放路径:/apps/stub_test/大家可以统一将jar包放置此处,当然也可以自定义)
2 启动关闭测试桩
Linux上启动测试桩命令:1>.#java -jar testStub.jar &
//该命令表示启动jar包
//注:加&表示将进程放置在后台运行
2>.#jobs
//查看后台运行的任务列表
3>.#nohup java -jar testStub.jar &
//如果想在退出终端后服务不终止则使用nohup命令,nohup的作用是即使退出终端,程序仍不会结束,使用nohup命令应注意该服务不会停止,不用时应注意将该进程kill
掉
//若出现下面提示信息,不是报错,它表示程序运行信息会输出到nohup.out
#nohup: ignoring input and appending output to `nohup.out'
4>.#jobs -l
如图所示,显示该服务的进程号
#kill -9 进程号
//干掉进程
3 注意事项
1>.在使用测试桩时,返回报文是作为一个xml(或json)文件放在外部进行读取的,这样便于测试在测试时可通过修改xml文件的形式进行更多场景的测试2>.如果在启动jar包时报错,注意是否是端口号被占用
#知识传送门:
https://github.com/russ44/easyMock
以上是我写的用于测试桩的mock平台,非常简单易懂,直接将项目打成war包部署tomcat容器即可运行。
该平台通过前台web页面管理接口,可作为轻量级的mock平台
相关文章推荐
- Android测试教程13--模拟服务器MockServer之Moco详细介绍
- HTTP服务端接口模拟工具-HttpServerMockTool 1 工具功能介绍 这个工具可以通过简单的配置达到快速模拟第三方HTTP服务端接口的作用,替代以前要手写servlet代码再放到to
- 详细介绍windows下使用python pylot进行网站压力测试
- 接口测试—-下篇,以/note/readnotes接口为例子详细介绍怎么做接口的
- Loadrunner模拟JSON接口请求进行测试
- 如何利用cURL和python对服务端和web端进行接口测试
- 使用mock进行接口模拟测试
- Loadrunner模拟JSON接口请求进行测试
- Loadrunner模拟JSON接口请求进行测试
- 详细介绍windows下使用python pylot进行网站压力测试
- 使用模拟对象(Mock Object)技术进行测试驱动开发
- 网络DOS测试命令详细介绍及使用方法举例
- java模拟并发操作进行压力测试
- loadrunner 对接口进行测试
- java模拟并发操作进行压力测试
- Java OpenSSL生成的RSA公私钥进行数据加解密详细介绍
- 模拟多用户进行压力测试
- MII、RMII、GMII接口的详细介绍
- Linux中的lo回环接口详细介绍
- 不知道大家用什么工具对Web程序进行不同版本的IE测试,向大家介绍一个工具,感觉还不错也许大家早就知道