标注@Rule

TestRule是一个工厂方法模式中的Creator角色——声明工厂方法。

package org.junit.rules;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
public interface TestRule {
Statement apply(Statement base, Description description);
}

因为工厂方法apply有參数base。因而TestRule将创建装饰模式中的装饰对象

【抽象类Statement声明操作evaluate()的接口。它作为一个回调接口,上层模块能够定义各种Statement的子类。提供evaluate()的方法体。而这一主要的技术与Rule结合,成为JUnit一个很重要的手段——能够说它是一个通用型的复合命令的构造方式。全然能够代替Statement的一些复合命令的子类如ExpectException等。

測试程序猿要使用Rule,必须编写代码。以下先介绍使用Rule的样例。

1.MyStatement——Statement的一个新的装饰对象。( JUnit之Rule的使用中的样例),地位等同于ExpectException。

package rule;
import static tool.Print.*;//pln(Object)
import org.junit.runners.model.Statement;
/**
*
* @author yqj2065
*/
public class MyStatement extends Statement {
private final Statement base;
public MyStatement( Statement base ) {
this.base = base;
} @Override public void evaluate() throws Throwable {
pln( "before...sth..sth" );
try {
base.evaluate();
} finally {
pln( "after...sth..sth" );
}
}
}

2.一个详细的工厂。也就是定义工厂方法的TestRule的子类。MyRule将创建一个Statement的新的装饰对象MyStatement。如同工厂方法模式的一般使用方法,详细工厂与详细产品一一相应。

package rule;
import org.junit.rules.TestRule;
import org.junit.runners.model.Statement;
import org.junit.runner.Description;
public class MyRule implements TestRule {
@Override
public Statement apply(Statement base, Description description) {
return new MyStatement( base );
}
}

3.使用新的装饰对象

用户类BlockJUnit4ClassRunner使用的是ExpectException等JUnit内建的Statement装饰对象;測试程序猿编写的Statement装饰对象,则须要通过@Rule,嵌入到单元測试类中

package rule;
import org.junit.Rule;
import org.junit.Test;
public class MyTest {
@Rule
public MyRule myRule = new MyRule(); @Test()
public void xx() {
System.out.println( "xx()..." );
}
}

在开发环境中执行MyTest,输出:

before...sth..sth

xx()...

after...sth..sth

例程 8 17标注Rule
package org.junit;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface Rule {}

注意:JUnit4.8中Rule标注并没有指定@Target(ElementType.FIELD),而4.10版本号中明白定义出来。Rule用于修饰測试单元类中一个特殊的域。该域必须是public、非static并且是org.junit.rules.TestRule子类型的引用变量(代替4.8版本号的org.junit.rules.MethodRule)。JUnit4.10版本号中还有一个标注@ClassRule,用于修饰測试单元类中static的TestRule子类型的引用变量。

TestRule

org.junit.rules.TestRule声明工厂方法,因为工厂方法apply有參数base,因而TestRule将创建装饰模式中的装饰对象。

然而,装饰对象仍然是一个Statement。

TestRule的各种实现类创建很多装饰对象。可是没有特别的名字。反正是一个Statement。

从JUnit框架设计的角度看,TestRule是工厂方法;而从測试程序猿思考问题的角度,TestRule及事实上现类,为单元測试制订了各种附加的规则/Rule。

在org.junit.rules包中的TestRule的实现类有:

1. TestWatcher

对base加以监控的Rule。它不会对结果进行改动。

TestWatcher以匿名类的方式创建Statement装饰对象。在@Override evaluate()时使用了模板方法模式

例程 8-4 TestWatchman
package org.junit.rules; import org.junit.internal.AssumptionViolatedException;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
public abstract class TestWatcher implements TestRule {
public Statement apply(final Statement base, final Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
starting(description);
try {
base.evaluate();
succeeded(description);
} catch (AssumptionViolatedException e) {
throw e;
} catch (Throwable t) {
failed(t, description);
throw t;
} finally {
finished(description);
}
}
};
}
protected void succeeded(Description description) { }
protected void failed(Throwable e, Description description) { }
protected void starting(Description description) { }
protected void finished(Description description) { }
}

TestWatcher的子类TestName是模板方法模式中的详细类角色。

publicvoid starting(FrameworkMethod method) {

fName=method.getName();

}

2. Verifier

使用了模板方法模式,以匿名类的方式创建Statement装饰对象,在base. evaluate()之后加入一个verify()操作。Verifier的子类ErrorCollector收集測试中的错误。

3. ExpectedException和Timeout

ExpectedException作为工厂创建装饰对象,其私有内部类ExpectedExceptionStatement全然等价于org.junit.internal.runners.statements.ExpectException的地位。可是,ExpectedException作为规则将作用于各种測试方法。而ExpectException作用于@Test(expected=xxx)修饰的方法

Timeout则是典型的工厂。返回一个装饰对象FailOnTimeout

package org.junit.rules;
import org.junit.internal.runners.statements.FailOnTimeout;
import org.junit.runner.Description;
import org.junit.runners.model.Statement; public class Timeout implements TestRule {
private final int fMillis; /**
* @param millis the millisecond timeout
*/
public Timeout(int millis) {
fMillis= millis;
} public Statement apply(Statement base, Description description) {
return new FailOnTimeout(base, fMillis);
}
}

4. ExternalResource

ExternalResource使用了模板方法模式。以匿名类的方式创建Statement装饰对象。在base. evaluate()之前before()中能够加入各种其它资源(file, socket, server, database connection),而after()中释放资源。其子类TemporaryFolder给出了一个样例。

【JUnit4.10源码分析】5.2 Rule的更多相关文章

  1. 【JUnit4.10源码分析】5 Statement

    假设要评选JUnit中最最重要的类型.或者说核心,无疑是org.junit.runners.model.Statement.Runner等类型看起来热闹而已. package org.junit.ru ...

  2. 【JUnit4.10源码分析】6.1 排序和过滤

    abstract class ParentRunner<T> extends Runner implements Filterable,Sortable 本节介绍排序和过滤. (尽管JUn ...

  3. 【JUnit4.10源码分析】3.4 Description与測试树

    Description使用组合模式描写叙述一个測试树.组合模式中全部元素都是Composite对象. Description有成员变量private final ArrayList<Descri ...

  4. JUnit源码分析 - 扩展 - 自定义Rule

    JUnit Rule简述 Rule是JUnit 4.7之后新加入的特性,有点类似于拦截器,可以在测试类或测试方法执行前后添加额外的处理,本质上是对@BeforeClass, @AfterClass, ...

  5. JUnit4.12 源码分析之TestClass

    1. TestClass // 源码:org.junit.runners.model.TestClass // 该方法主要提供方法校验和注解搜索 public class TestClass impl ...

  6. 10.源码分析---SOFARPC内置链路追踪SOFATRACER是怎么做的?

    SOFARPC源码解析系列: 1. 源码分析---SOFARPC可扩展的机制SPI 2. 源码分析---SOFARPC客户端服务引用 3. 源码分析---SOFARPC客户端服务调用 4. 源码分析- ...

  7. JUnit4.12 源码分析之Statement

    1. Statement 抽象类Statement作为命令模式的Command,只有一个方法 各种Runner作为命令模式中的Invoker,将发出各种Statement,来表示它们运行JUnit测试 ...

  8. JUnit4.12 源码分析(二)之TestRule

    1. TestRule TestRule和@Before,@After,@BeforeClass,@AfterClass功能类似,但是更加强大; JUnit 识别TestRule的两种方式: 方法级别 ...

  9. 11.源码分析---SOFARPC数据透传是实现的?

    先把栗子放上,让大家方便测试用: Service端 public static void main(String[] args) { ServerConfig serverConfig = new S ...

随机推荐

  1. [Backbone] Customzing Backbone

    Convert the AppointmentForm view below to use Mustache templating. Make sure you remember to change ...

  2. [Node.js]30. Level 6: Listen 'Question' from client, and then Answer the Question

    Clients can also answer each other questions, so let's build that feature by first listening for the ...

  3. 从servlet中获取spring的WebApplicationContext

    需要做一个参数初始化类,当web应用被加载时从数据库里取出相关的参数设置 ,并把这些参数放置到application里,jsp页面可以从中取出. 1.在web.xml中配置: <servlet& ...

  4. Web Service 的工作原理(转载)

    Web Service基本概念 Web Service也叫XML Web Service WebService是一种可以接收从Internet或者Intranet上的其它系统中传递过来的请求,轻量级的 ...

  5. php之快速入门学习-6(字符串变量)

    PHP 字符串变量 字符串变量用于存储并处理文本. PHP 中的字符串变量 字符串变量用于包含有字符的值. 在创建字符串之后,我们就可以对它进行操作了.您可以直接在函数中使用字符串,或者把它存储在变量 ...

  6. Android 笔记-Fragment 与 Activity之间传递数据

    Fragment 与 Activity之间传递数据有两种方法.一种是使用setArgument,一种是使用接口回调.以下先学习第一种方法. (1)使用setArgument方法: 为了便于理解,我在这 ...

  7. [Done]ftp使用小结

    基本命令: put 本地文件名 ftp文件名 get ftp文件名 本地文件名 mget ftp文件多个文件  注意使用该命令时先用 lcd切换本地路径 还有一些常用的  ls mkdir 等,参考 ...

  8. div最小高度的2种写法

    1.第一种写法: 原理:在IE6中,使用CSS定义div的高度的时候经常遇到这个问题,就是当div的最小高度小于一定的值以后,就会发现,无论你怎么设置最小高度,div的高度会固定在一个值不再发生变动, ...

  9. Windows 消息机制浅析

    1.       Windows 的历史 中国人喜欢以史为鉴,而事实也确实是,如果你能知道一件事情的来龙去脉,往往可以更容易地理解事物为什么会表现为当前这样的现状.所以,我的介绍性开场白通常会以一段历 ...

  10. Android仿掌上英雄联盟首页,实现折叠效果

    概述 仿掌上英雄联盟首页的demo 详细 代码下载:http://www.demodashi.com/demo/10695.html 首页大概分为几个部分 状态栏 标题栏 轮播图 切换的Tab 资讯列 ...