在RestFuse提供了多种单元测试的方式,这里只是关注常用的三种方式.
其中1.常见的请求一次
2.请求一次并回调.
3.多个请求.
在junit4中Statement可以用来执行调用.可以采用类似执行链的封装使用.在RestFuse中封装的Statement有多个,如BasicStatement:执行的普通请求相应.
HttpTestStatement:处理请求的回调和多个调用.
在Destination中Statement被调用:
源代码如下:
public Statement apply(Statement base, Description description) { Statement result; Statement result; if (hasAnnotation(description)) { this.requestStatement = new HttpTestStatement(base, description, this.testObject, this.baseUrl, this.proxyHost, this.proxyPort, this.context); result = this.requestStatement; } else { result = base; } return result; }
HttpTestStatement实现Statement主要代码封装如下:
public class HttpTestStatement extends Statement { static final String HTTP_PROXY_HOST = "http.proxyHost"; static final String HTTP_PROXY_PORT = "http.proxyPort"; private final Statement base; private final Description description; private final Object target; private final String baseUrl; private final String proxyHost; private final int proxyPort; private final RequestContext context; public HttpTestStatement(Statement base, Description description, Object target, String baseUrl, String proxyHost, int proxyPort, RequestContext context) { this.base = base; this.description = description; this.target = target; this.baseUrl = baseUrl; this.proxyHost = proxyHost; this.proxyPort = proxyPort; this.context = context; } public void evaluate() throws Throwable { setProxyProperties(); try { doEvaluate(); } finally { unsetProxyProperties(); } } private void setProxyProperties() { if (this.proxyHost != null) { System.setProperty("http.proxyHost", this.proxyHost); System.setProperty("http.proxyPort", String.valueOf(this.proxyPort)); } } private void doEvaluate() throws Throwable { Statement delegate = new BasicStatement(this.base, this); if (needsCallback()) delegate = new CallbackStatement(this.base, this, this.description, this.target); else if (needsPoll()) { delegate = new PollStatement(this.base, this, this.description, this.target); } delegate.evaluate(); } private void unsetProxyProperties() { Properties properties = System.getProperties(); properties.remove("http.proxyHost"); properties.remove("http.proxyPort"); } private boolean needsCallback() { Callback callbackAnnotation = (Callback) this.description .getAnnotation(Callback.class); return (callbackAnnotation != null); } private boolean needsPoll() { Poll pollAnnotation = (Poll) this.description.getAnnotation(Poll.class); return (pollAnnotation != null); } public Response sendRequest() { InternalRequest request = buildRequest(); return callService(request); } private InternalRequest buildRequest() { RequestConfiguration requestConfiguration = new RequestConfiguration( this.baseUrl, this.description, this.target); return requestConfiguration.createRequest(this.context); } private Response callService(InternalRequest request) { Method requestMethod = ((HttpTest) this.description .getAnnotation(HttpTest.class)).method(); Response result = null; if (requestMethod.equals(Method.GET)) result = request.get(); else if (requestMethod.equals(Method.POST)) result = request.post(); else if (requestMethod.equals(Method.DELETE)) result = request.delete(); else if (requestMethod.equals(Method.PUT)) result = request.put(); else if (requestMethod.equals(Method.HEAD)) result = request.head(); else if (requestMethod.equals(Method.OPTIONS)) { result = request.options(); } return result; } public void tryInjectResponse(Response response) { Field[] fields = this.target.getClass().getDeclaredFields(); for (Field field : fields) { Context contextAnnotation = (Context) field .getAnnotation(Context.class); if ((contextAnnotation != null) && (field.getType() == Response.class)) injectResponse(field, response); } } private void injectResponse(Field field, Response response) { field.setAccessible(true); try { field.set(this.target, response); } catch (Exception exception) { throw new IllegalStateException("Could not inject response.", exception); } } }
可以看出HttpTestStatement起了关键作用
1.setProxyProperties可以看出请求代理的处理.
2.doEvaluate回调和Poll的实现.
3.sendRequest处理了请求调用的过程
4.injectResponse注入单元测试的功能.
HttpTestStatement是怎样被RestFuse调用的呢?
1.首先在执行单元测试类中定义Destination.
2.执行单元执行的使用调用Rule.
3.Rule调用Statement.
4.Statement执行最后调用测试单元.