在junit中定义一些可以公用的规则(Rule),类似拦截器和拦截器链的概念.在Junit4版本中针对不同的版本Rule的接口不一样,在Junit4.11和Junit4.10 采用实现TestRule接口.在Junit4.8采用的MethodRule接口.
备注:
RestFuse使用1.2.0,
Junit采用4.10版本.
如在RestFuse中定义Destination实现TestRule接口.实现apply方法:
public Statement apply(Statement base, Description description);
使用如下:
package com.easyway.restfuse; import org.junit.Rule; import org.junit.runner.RunWith; import com.eclipsesource.restfuse.Destination; import com.eclipsesource.restfuse.HttpJUnitRunner; import com.eclipsesource.restfuse.Method; import com.eclipsesource.restfuse.Response; import com.eclipsesource.restfuse.annotation.Context; import com.eclipsesource.restfuse.annotation.HttpTest; /** * * @author longgangbai * */ @RunWith( HttpJUnitRunner.class ) public class RestfuseTest { @Rule public Destination destination = new Destination("", "http://restfuse.com" ); @Context private Response response; // will be injected after every request @HttpTest( method = Method.GET, path = "/" ) public void checkRestfuseOnlineStatus() { System.out.println( response); } }
在junit4中Rule怎么调用的呢?
在BlockJUnit4ClassRunner中的methodBlock中进行测试方法的各种操作.如BeforeMethod,AfterMethod等的组装为Statement .
protected Statement methodBlock(FrameworkMethod method) { Object test; try { test = new ReflectiveCallable() { protected Object runReflectiveCall() throws Throwable { return BlockJUnit4ClassRunner.this.createTest(); } }.run(); } catch (Throwable e) { return new Fail(e); } Statement statement = methodInvoker(method, test); statement = possiblyExpectingExceptions(method, test, statement); statement = withPotentialTimeout(method, test, statement); statement = withBefores(method, test, statement); statement = withAfters(method, test, statement); statement = withRules(method, test, statement); return statement; }
其中最后一个withRules,同时可以看出possiblyExpectingExceptions,withPotentialTimeout,withBefores,withAfters被不推荐使用.其实他们几个都可以采用Rule的方式现实,这也是不推荐使用的主要原因.
具体的Rule相关的源代码:
private Statement withRules(FrameworkMethod method, Object target, Statement statement) { List testRules = getTestRules(target); Statement result = statement; result = withMethodRules(method, testRules, target, result); result = withTestRules(method, testRules, result); return result; } private Statement withMethodRules(FrameworkMethod method, List<TestRule> testRules, Object target, Statement result) { for (MethodRule each : getMethodRules(target)) { if (!(testRules.contains(each))) { result = each.apply(result, method, target); } } return result; } private List<MethodRule> getMethodRules(Object target) { return rules(target); } protected List<MethodRule> rules(Object target) { return getTestClass().getAnnotatedFieldValues(target, Rule.class, MethodRule.class); } private Statement withTestRules(FrameworkMethod method, List<TestRule> testRules, Statement statement) { return new RunRules(statement, testRules, describeChild(method)); } protected List<TestRule> getTestRules(Object target) { List result = getTestClass().getAnnotatedMethodValues(target, Rule.class, TestRule.class); result.addAll(getTestClass().getAnnotatedFieldValues(target, Rule.class, TestRule.class)); return result; }
可以看出Rule不仅有类级别的还有方法的级别的.