写一个接口自动化测试代码的时候,测试环境崩溃了,但是又需要继续的调试,怎么办呢?
决定自己写一个mock server来返回接口响应,采用embedded jetty,日志使用logback。
需求
1、当用GET方法访问http://localhost:8080/version/1.0/versions/latest时,会返回如下JSON字符串:
{“code”:”0000”,”content”:{“newVersion”:0},”message”:”成功”}
2、当使用POST方法访问http://localhost:8080/auth/1.0/tokens时,会返回如下的JSON字符串:
{“code”:”0000”,”content”:{…},”message”:”成功”}
首先是在maven中加入如下的依赖:
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>9.4.0.RC3</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
然后是mock server的类:
package com.szsharelink.test.mock;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
/**
* Created by Liliangxi on 2017/8/12.
*/
public class EmbeddedJettyServer {
private Server server;
private int port = 8888;
public EmbeddedJettyServer(int port) {
this.port = port;
}
public void start() throws Exception{
server = new Server(port);
ContextHandler contextVersion = new ContextHandler("/version/1.0/versions/latest");
contextVersion.setHandler(new GetVersionHandler());
ContextHandler contextToken = new ContextHandler("/auth/1.0/tokens");
contextToken.setAllowNullPathInfo(true);
contextToken.setHandler(new PostTokenHandler());
ContextHandlerCollection contexts = new ContextHandlerCollection();
contexts.addHandler(contextVersion);
contexts.addHandler(contextToken);
server.setHandler(contexts);
server.start();
//server.join(); // 不能有这个,否则后面的client调用不会进行
}
public void stop(){
try{
server.stop();
}catch (Exception e){
}
}
}
Handler的代码如下:
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Created by Liliangxi on 2017/8/12.
*/
public class GetVersionHandler extends AbstractHandler{
@Override
public void handle(String s, Request request, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException, ServletException {
// Declare response encoding and types
httpServletResponse.setContentType("application/json; charset=utf-8");
// Declare response status code
httpServletResponse.setStatus(HttpServletResponse.SC_OK);
// Write back response
// {"code":"0000","content":{"newVersion":0},"message":"成功"}
httpServletResponse.getWriter().println("{\"code\":\"0000\",\"content\":{\"newVersion\":0},\"message\":\"成功\"}");
// Inform jetty that this request has now been handled
request.setHandled(true);
}
}
BeforeClass函数里这样启动:
@BeforeClass
public void before() throws Exception{
RestAssured.baseURI = "http://192.168.0.60";
RestAssured.port = 8080;
RestAssured.registerParser("text/plain", Parser.JSON);
EmbeddedJettyServer mockServer = new EmbeddedJettyServer(8080);
mockServer.start();
// do other things ...
}
AfterClass函数里停止jetty服务器:
@AfterClass
public void afterClass(){
mockServer.stop();
}
文章里有几个重点需要注意:
1、contextToken.setAllowNullPathInfo(true);
很多人写程序向jetty发POST消息,会返回302重定向错误。
有两种处理方式(其实只有一种),一种是请求消息的地址最后加上“/”,也就是这样请求:http://IP:port/url/。一种就是文中使用的方法了。
2、server.join();
如果按照网上的例子,在start后写了join,那么接下来的client请求就不会发送出去。
3、使用logback的时候如何避免jetty打大量的日志?
在logback.xml中这样写:
<logger name="org.eclipse.jetty" level="INFO" />
这样,就可以在@Test里写各种测试了,往这个embedded jetty服务器上发送消息,并且得到设置好的响应消息。