- 浏览: 7847073 次
- 性别:
- 来自: 广州
文章分类
- 全部博客 (2425)
- 软件工程 (75)
- JAVA相关 (662)
- ajax/web相关 (351)
- 数据库相关/oracle (218)
- PHP (147)
- UNIX/LINUX/FREEBSD/solaris (118)
- 音乐探讨 (1)
- 闲话 (11)
- 网络安全等 (21)
- .NET (153)
- ROR和GOG (10)
- [网站分类]4.其他技术区 (181)
- 算法等 (7)
- [随笔分类]SOA (8)
- 收藏区 (71)
- 金融证券 (4)
- [网站分类]5.企业信息化 (3)
- c&c++学习 (1)
- 读书区 (11)
- 其它 (10)
- 收藏夹 (1)
- 设计模式 (1)
- FLEX (14)
- Android (98)
- 软件工程心理学系列 (4)
- HTML5 (6)
- C/C++ (0)
- 数据结构 (0)
- 书评 (3)
- python (17)
- NOSQL (10)
- MYSQL (85)
- java之各类测试 (18)
- nodejs (1)
- JAVA (1)
- neo4j (3)
- VUE (4)
- docker相关 (1)
最新评论
-
xiaobadi:
jacky~~~~~~~~~
推荐两个不错的mybatis GUI生成工具 -
masuweng:
(转)JAVA获得机器码的实现 -
albert0707:
有些扩展名为null
java 7中可以判断文件的contenttype了 -
albert0707:
非常感谢!!!!!!!!!
java 7中可以判断文件的contenttype了 -
zhangle:
https://zhuban.me竹板共享 - 高效便捷的文档 ...
一个不错的网络白板工具
http://haibin369.iteye.com/blog/2088541
一、Rule简介
Rule是JUnit4中的新特性,它让我们可以扩展JUnit的功能,灵活地改变测试方法的行为。JUnit中用@Rule和@ClassRule两个注解来实现Rule扩展,这两个注解需要放在实现了TestRule借口的成员变量(@Rule)或者静态变量(@ClassRule)上。@Rule和@ClassRule的不同点是,@Rule是方法级别的,每个测试方法执行时都会调用被注解的Rule,而@ClassRule是类级别的,在执行一个测试类的时候只会调用一次被注解的Rule
二、JUnit内置Rule
JUnit4中默认实现了一些常用的Rule:
TemporaryFolder Rule
使用这个Rule可以创建一些临时目录或者文件,在一个测试方法结束之后,系统会自动清空他们。
//创建TemporaryFolder Rule
//可以在构造方法上加入路径参数来指定临时目录,否则使用系统临时目录
@Rule
public TemporaryFolder tempFolder = new TemporaryFolder();
@Test
public void testTempFolderRule() throws IOException {
//在系统的临时目录下创建文件或者目录,当测试方法执行完毕自动删除
tempFolder.newFile("test.txt");
tempFolder.newFolder("test");
}
ExternalResource Rule
ExternalResource 是TemporaryFolder的父类,主要用于在测试之前创建资源,并在测试完成后销毁。
File tempFile;
@Rule
public ExternalResource extResource = new ExternalResource() {
//每个测试执行之前都会调用该方法创建一个临时文件
@Override
protected void before() throws Throwable {
tempFile = File.createTempFile("test", ".txt");
}
//每个测试执行之后都会调用该方法删除临时文件
@Override
protected void after() {
tempFile.delete();
}
};
@Test
public void testExtResource() throws IOException {
System.out.println(tempFile.getCanonicalPath());
}
ErrorCollector Rule
ErrorCollector允许我们收集多个错误,并在测试执行完后一次过显示出来
@Rule
public ErrorCollector errorCollector = new ErrorCollector();
@Test
public void testErrorCollector() {
errorCollector.addError(new Exception("Test Fail 1"));
errorCollector.addError(new Throwable("fff"));
}
Verifier Rule
Verifier是ErrorCollector的父类,可以在测试执行完成之后做一些校验,以验证测试结果是不是正确
String result;
@Rule
public Verifier verifier = new Verifier() {
//当测试执行完之后会调用verify方法验证结果,抛出异常表明测试失败
@Override
protected void verify() throws Throwable {
if (!"Success".equals(result)) {
throw new Exception("Test Fail.");
}
}
};
@Test
public void testVerifier() {
result = "Fail";
}
TestWatcher Rule
TestWatcher 定义了五个触发点,分别是测试成功,测试失败,测试开始,测试完成,测试跳过,能让我们在每个触发点执行自定义的逻辑。
@Rule
public TestWatcher testWatcher = new TestWatcher() {
@Override
protected void succeeded(Description description) {
System.out.println(description.getDisplayName() + " Succeed");
}
@Override
protected void failed(Throwable e, Description description) {
System.out.println(description.getDisplayName() + " Fail");
}
@Override
protected void skipped(AssumptionViolatedException e, Description description) {
System.out.println(description.getDisplayName() + " Skipped");
}
@Override
protected void starting(Description description) {
System.out.println(description.getDisplayName() + " Started");
}
@Override
protected void finished(Description description) {
System.out.println(description.getDisplayName() + " finished");
}
};
@Test
public void testTestWatcher() {
/*
测试执行后会有以下输出:
testTestWatcher(org.haibin369.test.RulesTest) Started
Test invoked
testTestWatcher(org.haibin369.test.RulesTest) Succeed
testTestWatcher(org.haibin369.test.RulesTest) finished
*/
System.out.println("Test invoked");
}
TestName Rule
TestName能让我们在测试中获取目前测试方法的名字。
@Rule
public TestName testName = new TestName();
@Test
public void testTestName() {
//打印出测试方法的名字testTestName
System.out.println(testName.getMethodName());
}
Timeout与ExpectedException Rule
分别用于超时测试与异常测试,在JUnit4学习笔记(一):基本应用中有提到,这里不再举例。
三、实现原理与部分源码解析
在Junit4的默认Test Runner - org.junit.runners.BlockJUnit4ClassRunner中,有一个methodBlock方法:
protected Statement methodBlock(FrameworkMethod method) {
Object test;
try {
test = new ReflectiveCallable() {
@Override
protected Object runReflectiveCall() throws Throwable {
return 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;
}
在JUnit执行每个测试方法之前,methodBlock方法都会被调用,用于把该测试包装成一个Statement。Statement代表一个具体的动作,例如测试方法的执行,Before方法的执行或者Rule的调用,类似于J2EE中的Filter,Statement也使用了责任链模式,将Statement层层包裹,就能形成一个完整的测试,JUnit最后会执行这个Statement。从上面代码可以看到,有以下内容被包装进Statement中:
1)测试方法的执行;
2)异常测试,对应于@Test(expected=XXX.class);
3)超时测试,对应与@Test(timeout=XXX);
4)Before方法,对应于@Before注解的方法;
5)After方法,对应于@After注解的方法;
6)Rule的执行。
在Statement中,可以用evaluate方法控制Statement执行的先后顺序,比如Before方法对应的Statement - RunBefores:
public class RunBefores extends Statement {
private final Statement fNext;
private final Object fTarget;
private final List<FrameworkMethod> fBefores;
public RunBefores(Statement next, List<FrameworkMethod> befores, Object target) {
fNext = next;
fBefores = befores;
fTarget = target;
}
@Override
public void evaluate() throws Throwable {
for (FrameworkMethod before : fBefores) {
before.invokeExplosively(fTarget);
}
fNext.evaluate();
}
}
在evaluate中,所有Before方法会先被调用,因为Before方法必须要在测试执行之前调用,然后再执行fNext.evaluate()调用下一个Statement。
理解了Statement,再看回Rule的接口org.junit.rules.TestRule:
public interface TestRule {
Statement apply(Statement base, Description description);
}
里面只有一个apply方法,用于包裹上级Statement并返回一个新的Statement。因此实现Rule主要是需要实现一个Statement。
四、自定义Rule
通过上面的分析,我们大概知道了如何实现一个Rule,下面是一个例子:
/*
用于循环执行测试的Rule,在构造函数中给定循环次数。
*/
public class LoopRule implements TestRule{
private int loopCount;
public LoopRule(int loopCount) {
this.loopCount = loopCount + 1;
}
@Override
public Statement apply(final Statement base, Description description) {
return new Statement() {
//在测试方法执行的前后分别打印消息
@Override
public void evaluate() throws Throwable {
for (int i = 1; i < loopCount; i++) {
System.out.println("Loop " + i + " started!");
base.evaluate();
System.out.println("Loop "+ i + " finished!");
}
}
};
}
}
使用该自定义的Rule:
@Rule
public LoopRule loopRule = new LoopRule(3);
@Test
public void testLoopRule() {
System.out.println("Test invoked!");
}
执行后打印出以下信息:
Java代码 收藏代码
Loop 1 started!
Test invoked!
Loop 1 finished!
Loop 2 started!
Test invoked!
Loop 2 finished!
Loop 3 started!
Test invoked!
Loop 3 finished!
一、Rule简介
Rule是JUnit4中的新特性,它让我们可以扩展JUnit的功能,灵活地改变测试方法的行为。JUnit中用@Rule和@ClassRule两个注解来实现Rule扩展,这两个注解需要放在实现了TestRule借口的成员变量(@Rule)或者静态变量(@ClassRule)上。@Rule和@ClassRule的不同点是,@Rule是方法级别的,每个测试方法执行时都会调用被注解的Rule,而@ClassRule是类级别的,在执行一个测试类的时候只会调用一次被注解的Rule
二、JUnit内置Rule
JUnit4中默认实现了一些常用的Rule:
TemporaryFolder Rule
使用这个Rule可以创建一些临时目录或者文件,在一个测试方法结束之后,系统会自动清空他们。
//创建TemporaryFolder Rule
//可以在构造方法上加入路径参数来指定临时目录,否则使用系统临时目录
@Rule
public TemporaryFolder tempFolder = new TemporaryFolder();
@Test
public void testTempFolderRule() throws IOException {
//在系统的临时目录下创建文件或者目录,当测试方法执行完毕自动删除
tempFolder.newFile("test.txt");
tempFolder.newFolder("test");
}
ExternalResource Rule
ExternalResource 是TemporaryFolder的父类,主要用于在测试之前创建资源,并在测试完成后销毁。
File tempFile;
@Rule
public ExternalResource extResource = new ExternalResource() {
//每个测试执行之前都会调用该方法创建一个临时文件
@Override
protected void before() throws Throwable {
tempFile = File.createTempFile("test", ".txt");
}
//每个测试执行之后都会调用该方法删除临时文件
@Override
protected void after() {
tempFile.delete();
}
};
@Test
public void testExtResource() throws IOException {
System.out.println(tempFile.getCanonicalPath());
}
ErrorCollector Rule
ErrorCollector允许我们收集多个错误,并在测试执行完后一次过显示出来
@Rule
public ErrorCollector errorCollector = new ErrorCollector();
@Test
public void testErrorCollector() {
errorCollector.addError(new Exception("Test Fail 1"));
errorCollector.addError(new Throwable("fff"));
}
Verifier Rule
Verifier是ErrorCollector的父类,可以在测试执行完成之后做一些校验,以验证测试结果是不是正确
String result;
@Rule
public Verifier verifier = new Verifier() {
//当测试执行完之后会调用verify方法验证结果,抛出异常表明测试失败
@Override
protected void verify() throws Throwable {
if (!"Success".equals(result)) {
throw new Exception("Test Fail.");
}
}
};
@Test
public void testVerifier() {
result = "Fail";
}
TestWatcher Rule
TestWatcher 定义了五个触发点,分别是测试成功,测试失败,测试开始,测试完成,测试跳过,能让我们在每个触发点执行自定义的逻辑。
@Rule
public TestWatcher testWatcher = new TestWatcher() {
@Override
protected void succeeded(Description description) {
System.out.println(description.getDisplayName() + " Succeed");
}
@Override
protected void failed(Throwable e, Description description) {
System.out.println(description.getDisplayName() + " Fail");
}
@Override
protected void skipped(AssumptionViolatedException e, Description description) {
System.out.println(description.getDisplayName() + " Skipped");
}
@Override
protected void starting(Description description) {
System.out.println(description.getDisplayName() + " Started");
}
@Override
protected void finished(Description description) {
System.out.println(description.getDisplayName() + " finished");
}
};
@Test
public void testTestWatcher() {
/*
测试执行后会有以下输出:
testTestWatcher(org.haibin369.test.RulesTest) Started
Test invoked
testTestWatcher(org.haibin369.test.RulesTest) Succeed
testTestWatcher(org.haibin369.test.RulesTest) finished
*/
System.out.println("Test invoked");
}
TestName Rule
TestName能让我们在测试中获取目前测试方法的名字。
@Rule
public TestName testName = new TestName();
@Test
public void testTestName() {
//打印出测试方法的名字testTestName
System.out.println(testName.getMethodName());
}
Timeout与ExpectedException Rule
分别用于超时测试与异常测试,在JUnit4学习笔记(一):基本应用中有提到,这里不再举例。
三、实现原理与部分源码解析
在Junit4的默认Test Runner - org.junit.runners.BlockJUnit4ClassRunner中,有一个methodBlock方法:
protected Statement methodBlock(FrameworkMethod method) {
Object test;
try {
test = new ReflectiveCallable() {
@Override
protected Object runReflectiveCall() throws Throwable {
return 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;
}
在JUnit执行每个测试方法之前,methodBlock方法都会被调用,用于把该测试包装成一个Statement。Statement代表一个具体的动作,例如测试方法的执行,Before方法的执行或者Rule的调用,类似于J2EE中的Filter,Statement也使用了责任链模式,将Statement层层包裹,就能形成一个完整的测试,JUnit最后会执行这个Statement。从上面代码可以看到,有以下内容被包装进Statement中:
1)测试方法的执行;
2)异常测试,对应于@Test(expected=XXX.class);
3)超时测试,对应与@Test(timeout=XXX);
4)Before方法,对应于@Before注解的方法;
5)After方法,对应于@After注解的方法;
6)Rule的执行。
在Statement中,可以用evaluate方法控制Statement执行的先后顺序,比如Before方法对应的Statement - RunBefores:
public class RunBefores extends Statement {
private final Statement fNext;
private final Object fTarget;
private final List<FrameworkMethod> fBefores;
public RunBefores(Statement next, List<FrameworkMethod> befores, Object target) {
fNext = next;
fBefores = befores;
fTarget = target;
}
@Override
public void evaluate() throws Throwable {
for (FrameworkMethod before : fBefores) {
before.invokeExplosively(fTarget);
}
fNext.evaluate();
}
}
在evaluate中,所有Before方法会先被调用,因为Before方法必须要在测试执行之前调用,然后再执行fNext.evaluate()调用下一个Statement。
理解了Statement,再看回Rule的接口org.junit.rules.TestRule:
public interface TestRule {
Statement apply(Statement base, Description description);
}
里面只有一个apply方法,用于包裹上级Statement并返回一个新的Statement。因此实现Rule主要是需要实现一个Statement。
四、自定义Rule
通过上面的分析,我们大概知道了如何实现一个Rule,下面是一个例子:
/*
用于循环执行测试的Rule,在构造函数中给定循环次数。
*/
public class LoopRule implements TestRule{
private int loopCount;
public LoopRule(int loopCount) {
this.loopCount = loopCount + 1;
}
@Override
public Statement apply(final Statement base, Description description) {
return new Statement() {
//在测试方法执行的前后分别打印消息
@Override
public void evaluate() throws Throwable {
for (int i = 1; i < loopCount; i++) {
System.out.println("Loop " + i + " started!");
base.evaluate();
System.out.println("Loop "+ i + " finished!");
}
}
};
}
}
使用该自定义的Rule:
@Rule
public LoopRule loopRule = new LoopRule(3);
@Test
public void testLoopRule() {
System.out.println("Test invoked!");
}
执行后打印出以下信息:
Java代码 收藏代码
Loop 1 started!
Test invoked!
Loop 1 finished!
Loop 2 started!
Test invoked!
Loop 2 finished!
Loop 3 started!
Test invoked!
Loop 3 finished!
发表评论
-
复习:强迫线程顺序执行方式
2019-01-03 23:42 1472方法1: 三个线程,t1,t2,t3,如果一定要按顺序执行, ... -
(转)不错的前后端处理异常的方法
2019-01-02 23:16 1962前言 在 Web 开发中, 我们经常会需要处理各种异常, 这是 ... -
info q的极客时间大咖说等资料下载
2018-08-15 08:40 3408info q的极客时间大咖说等资料下载,还有不少思维导图 链 ... -
CXF 客户端超时时间设置(非Spring配置方式)
2018-07-03 22:38 2175import org.apache.cxf.endpoint. ... -
(转)synchronized关键字画像:正确打开方式
2018-06-14 09:25 443https://mp.weixin.qq.com/s/b3Sx ... -
CountDownLatch的例子
2018-06-13 14:10 627public class StatsDemo { ... -
两道面试题,带你解析Java类加载机制
2018-06-12 16:29 549https://mp.weixin.qq.com/s/YTa0 ... -
Spring中获取request的几种方法,及其线程安全性分析
2018-06-11 09:03 621https://mp.weixin.qq.com/s/KeFJ ... -
内部类小结
2018-06-06 10:25 393https://mp.weixin.qq.com/s/hErv ... -
JVM虚拟机小结1
2018-06-04 20:43 4601 jps -l //列出详细的类名和进程ID 2)jps ... -
windows下自带命令行工具查看CPU资源情况等
2018-06-04 12:53 3037微软提供了不少命令行 ... -
(收藏)深入分析Java的序列化与反序列化
2018-05-30 15:21 551https://mp.weixin.qq.com/s/T2Bn ... -
apache common包中的序列化工具
2018-05-30 09:10 1771什么是序列化 我们的 ... -
JAVA8 JVM的变化: 元空间(Metaspace)
2018-05-24 22:30 903本文将会分享至今为至我收集的关于永久代(Permanent G ... -
(转)服务器性能指标(一)——负载(Load)分析及问题排查
2018-05-21 21:03 1259原创: Hollis Hollis 负载 ... -
(转)对象复用
2018-05-20 15:27 802public class Student { priv ... -
mapreduce中入门中要注意的几点
2018-05-06 08:59 614在 mapreduce中,比如有如下的词: I love b ... -
HDFS的基本操作
2018-05-02 21:47 872-mkdir 在HDFS创建目录 ... -
一个不错的开源工具类,专门用来解析日志头部的,好用
2018-05-02 20:00 703一个不错的开源工具类,专门用来解析日志头部的,好用。 http ... -
介绍个不错的RESTFUL MOCK的工具wiremock
2018-04-27 21:02 1850介绍个不错的RESTFUL MOCK的工具wiremock,地 ...
相关推荐
NULL 博文链接:https://bijian1013.iteye.com/blog/2119792
NULL 博文链接:https://bijian1013.iteye.com/blog/2119786
Junit学习笔记,希望有用~~~~~~~~~~~~~~~~~~~~~~
junit4学习文档,有实例,非常详细,不懂的可以参考
赠送jar包:junit-jupiter-engine-5.8.2.jar; 赠送原API文档:junit-jupiter-engine-5.8.2-javadoc.jar; 赠送源代码:junit-jupiter-engine-5.8.2-sources.jar; 赠送Maven依赖信息文件:junit-jupiter-engine-...
JUnit4是JUnit框架有史以来的最大改进,其主要目标便是利用Java5的Annotation特性简化测试用例的编写。 先简单解释一下什么是Annotation,这个单词一般是翻译成元数据。元数据是什么?元数据就是描述数据的数据。也...
JUnit是一款由Erich Gamma(《设计模式》的作者)和Kent Beck(极限编程的提出者)编写的开源的回归测试框架,供Java编码人员做单元测试之用。当前版本4.1,可以从www.junit.org网站上获得。与早期的JUnit 3相比,...
junit4单元测试报错:method initializationerror not found 缺少jar包导致,总共需要三个jar包:junit-4.11.jar,hamcrest-core-1.3.rc2.jar,hamcrest-library-1.3.rc2.jar,都在压缩包里了。
JUnit 4所需system-rules.jar依赖包,主要包含:system-rules-1.16.1.jar,system-rules-1.17.1.jar,system-rules-1.18.0.jar
junit-vintage-engine-5.6.2.jarjunit-vintage-engine-5.6.2.jarjunit-vintage-engine-5.6.2.jar
本人小白,开始学习Android,记录自己的错误瞬间,大神不要喷我,哈哈! 安装好android studio后,测试并创建了一个HelloWord project,按照提示一步一步设置完成后,发现要下载一些gradle resource,结果下载了一夜...
赠送jar包:junit-jupiter-api-5.5.2.jar; 赠送原API文档:junit-jupiter-api-5.5.2-javadoc.jar; 赠送源代码:junit-jupiter-api-5.5.2-sources.jar; 赠送Maven依赖信息文件:junit-jupiter-api-5.5.2.pom; ...
赠送jar包:junit-jupiter-api-5.4.2.jar; 赠送原API文档:junit-jupiter-api-5.4.2-javadoc.jar; 赠送源代码:junit-jupiter-api-5.4.2-sources.jar; 赠送Maven依赖信息文件:junit-jupiter-api-5.4.2.pom; ...
Junit学习笔记和课件,欢迎学习爱好者下载资源,共同学习。。
以一个简单的DEMO介绍如何在Eclipse下使用JUnit4。供初次接触JUnit的同学学习
现在的版本都4.3.1,3.8.1的感觉好象不好找,虽然www.junit.org能够找到,但对我们这种英语不好的来说,还是不好找,再说了,现在好多的教程都是以3.8.1来写的,所以在这里把我找到的3.8.1传上来供大家以后下载 博文链接:...
赠送jar包:junit-jupiter-engine-5.8.0-M1.jar; 赠送原API文档:junit-jupiter-engine-5.8.0-M1-javadoc.jar; 赠送源代码:junit-jupiter-engine-5.8.0-M1-sources.jar; 赠送Maven依赖信息文件:junit-jupiter-...
使用Junit4.12需要用的两个包,官网在国内无法下载
JUnit4
JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage,包含依赖包:junit-jupiter-5.5.1.jar,junit-jupiter-engine-5.5.1.jar,junit-jupiter-params-5.5.1.jar,junit-platform-launcher-1.5.1.jar,junit-...