博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于JUnit的学习笔记总结
阅读量:7143 次
发布时间:2019-06-29

本文共 6531 字,大约阅读时间需要 21 分钟。

hot3.png

我们通常在一个class里面定义一些方法,这些方法最终被执行是通过函数

org.junit.runners.BlockJUnit4ClassRunner.runChild  被触发。

源码如下:

@Override    protected void runChild(final FrameworkMethod method, RunNotifier notifier) {    	//获得描述        Description description = describeChild(method);        //是否需要被忽略,如果被忽略就触发fireTestIgnored函数        if (isIgnored(method)) {            notifier.fireTestIgnored(description);        } else {        	//正常情况下,都要走到本行            runLeaf(methodBlock(method), description, notifier);        }    }

然后,进入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);        }

证明如下:

Step completed: "thread=main", org.junit.runners.BlockJUnit4ClassRunner$1.
(), line=263 bci=9263 test = new ReflectiveCallable() {main[1] step> Step completed: "thread=main", org.junit.runners.BlockJUnit4ClassRunner.methodBlock(), line=268 bci=8268 }.run();main[1] step> Step completed: "thread=main", org.junit.internal.runners.model.ReflectiveCallable.run(), line=12 bci=012 return runReflectiveCall();main[1] step> Step completed: "thread=main", org.junit.runners.BlockJUnit4ClassRunner$1.runReflectiveCall(), line=266 bci=0266 return createTest();main[1] step> Step completed: "thread=main", org.junit.runners.BlockJUnit4ClassRunner.createTest(), line=217 bci=0217 return getTestClass().getOnlyConstructor().newInstance();

看看getOnlyConstructor是个什么鬼!

Step completed: "thread=main", org.junit.runners.BlockJUnit4ClassRunner.createTest(), line=217 bci=4217            return getTestClass().getOnlyConstructor().newInstance();main[1] step> Step completed: "thread=main", org.junit.runners.model.TestClass.getOnlyConstructor(), line=203 bci=0203            Constructor
[] constructors = clazz.getConstructors();main[1] next> Step completed: "thread=main", org.junit.runners.model.TestClass.getOnlyConstructor(), line=204 bci=8204 Assert.assertEquals(1, constructors.length);main[1] next> Step completed: "thread=main", org.junit.runners.model.TestClass.getOnlyConstructor(), line=205 bci=15205 return constructors[0];

也就是说,只容许有1个构造函数!

我看了下我的测试类,没有显示提供构造函数,JVM默认提供了一个默认构造函数!

---继续debug生成实例

Step completed: "thread=main", org.junit.runners.BlockJUnit4ClassRunner.createTest(), line=217 bci=7217            return getTestClass().getOnlyConstructor().newInstance();main[1] print getTestClass().getOnlyConstructor() getTestClass().getOnlyConstructor() = "public mytest.CalculatorTest()"main[1] step> Step completed: "thread=main", mytest.CalculatorTest.
(), line=7 bci=17 public class CalculatorTest {main[1] step> Step completed: "thread=main", org.junit.runners.BlockJUnit4ClassRunner.createTest(), line=217 bci=14217 return getTestClass().getOnlyConstructor().newInstance();

到这里,一个测试类的实例就生成了!

Step completed: "thread=main", org.junit.runners.BlockJUnit4ClassRunner.methodBlock(), line=263 bci=11263                test = new ReflectiveCallable() {main[1] step> Step completed: "thread=main", org.junit.runners.BlockJUnit4ClassRunner.methodBlock(), line=269 bci=12269            } catch (Throwable e) {main[1] print test test = "mytest.CalculatorTest@66d33a"

继续debug,接下来会执行下面的一些代码

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;

先看第一行

Statement statement = methodInvoker(method, test);

debug结果为

Step completed: "thread=main", org.junit.runners.BlockJUnit4ClassRunner.methodBlock(), line=273 bci=25273            Statement statement = methodInvoker(method, test);main[1] step> Step completed: "thread=main", org.junit.runners.BlockJUnit4ClassRunner.methodInvoker(), line=290 bci=0290            return new InvokeMethod(method, test);main[1] print method method = "public void mytest.CalculatorTest.evaluatesExpression()"main[1] print test test = "mytest.CalculatorTest@66d33a"main[1] step> Step completed: "thread=main", org.junit.internal.runners.statements.InvokeMethod.
(), line=10 bci=010 public InvokeMethod(FrameworkMethod testMethod, Object target) {main[1] step> Step completed: "thread=main", org.junit.runners.model.Statement.
(), line=10 bci=010 public abstract class Statement {main[1] step> Step completed: "thread=main", org.junit.internal.runners.statements.InvokeMethod.
(), line=11 bci=411 this.testMethod = testMethod;main[1] step> Step completed: "thread=main", org.junit.internal.runners.statements.InvokeMethod.
(), line=12 bci=912 this.target = target;main[1] step> Step completed: "thread=main", org.junit.internal.runners.statements.InvokeMethod.
(), line=13 bci=1413 }main[1] step> Step completed: "thread=main", org.junit.runners.BlockJUnit4ClassRunner.methodInvoker(), line=290 bci=9290 return new InvokeMethod(method, test);main[1] step> Step completed: "thread=main", org.junit.runners.BlockJUnit4ClassRunner.methodBlock(), line=273 bci=31273 Statement statement = methodInvoker(method, test);

很显然,这个statement对象标识了执行一个类的某个方法

继续看第2行,

        statement = possiblyExpectingExceptions(method, test, statement);

        statement = withPotentialTimeout(method, test, statement);

这个主要是跟异常捕捉和执行超时有关,暂时忽略。

下面还有3行,代码如下:

statement = withBefores(method, test, statement);		statement = withAfters(method, test, statement);		statement = withRules(method, test, statement);

这个主要是确定方法的执行顺序,我们以第一个withBefores为例

执行时候,触发下面的代码

public RunBefores(Statement next, List
befores, Object target) { this.next = next; this.befores = befores; this.target = target; } @Override public void evaluate() throws Throwable { for (FrameworkMethod before : befores) { before.invokeExplosively(target); } next.evaluate(); }

这个就不用解释了吧。

---

那么,这里就可以顺利执行完一个测试流程。

转载于:https://my.oschina.net/qiangzigege/blog/830081

你可能感兴趣的文章
dos命令dir查找文件的用法及实例
查看>>
Hadoop守护进程【简--】
查看>>
uboot中gd的定义和使用
查看>>
Tcpdump MySQL Query
查看>>
mac jdbc连接mysql
查看>>
Activity生命周期的学习以及Logcat的使用
查看>>
【TYVJ】1338 QQ农场(最大流+最大权闭合图)
查看>>
一个睡五分钟等于六个钟头的方法
查看>>
Material Designer的低版本兼容实现(五)—— ActivityOptionsCompat
查看>>
Mysql监控工具小集合
查看>>
POJ 1654 Area 计算几何
查看>>
Linux下Nginx+Tomcat整合的安装与配置
查看>>
Python的安装和详细配置(转)
查看>>
FloatingActionButton
查看>>
[再寄小读者之数学篇](2014-11-24 Abel 定理)
查看>>
iText导出pdf、word、图片
查看>>
android脚步---不同界面之间切换
查看>>
降压转换器 (Buck)
查看>>
Wami Map Project – 开源的 OSM API 服务
查看>>
【BZOJ】2946: [Poi2000]公共串
查看>>