最近对JUnit和Mockito的内部实现比较感兴趣,将在接下来的一段时间,和大家一起深入代码细节。
王侯将相,宁有种乎 (JUnit也没啥Magic吧)
阅读前提
听说过Java Annotation
使用过JUnit
知道
@Before, @After, @Test
对JUnit的内部实现有兴趣
代码版本: junit 4.12
代码搜索工具: http://grepcode.com/
常用符号
_
: 用来略去代码段中无关紧要的parameter...
: 用来略去无关紧要的代码实现
Example
下面是一个很简单的JUunit Test Class
public class SampleTest {
@Before
protected void setUp(){ ... }
@Test
public void test1(){ ... }
@After
public void tearDown(){ ... }
}
本文要解答的问题:@Before
, @Test
, @After
如何影响test workflow的?
Q&A
Q1. 如何提取一个函数的Annotation信息?
A: 任何Java提供了Method::getDeclaredAnnotations()
Q2. 如何把SampleTest里的methods都罗列出来?
A: Java提供了Class::getDeclaredMethods()
Q3: @Before, @Test, @After
的执行顺序如何保证的?
A: 在junit的BlockJUnit4ClassRunner class中有一段代码:
Statement statement = methodInvoker(method, _);
statement = withBefores(method, _, statement);
statement = withAfters(method, _, statement);
http://grepcode.com/file/repo1.maven.org...
Statement
可以看做是一个函数封装(Functional Interface),内部只有一个execute()
函数。method
是被@Test
修饰的测试函数(本例中的test1()
),withBefores
把SampleClass
中被@Before
修饰的所有函数找出来,然后封装成一个新的Statement
。
//比如说,可以用下面的naive实现
void withBefores(Method m, _, Statement statement) {
// 利用Q1和Q2的知识点把@Before修饰的函数都找出来
List<Method> befores = ...
return new Statement{
@Override
public execute() {
for (Method b : befores) {
b.execute();
}
m.execute();
}
}
}
Q4: Q3中的BlockJUnit4ClassRunner
和SampleTest
搅合到一起的?
A: 请自己去看BlockJUnit4ClassRunner
的constructor的parameter是什么。
Summary
利用Java原生的
getDeclaredAnnotations
和getDeclaredMethods
,可以轻松地得到测试类SampleTest中函数的annotations。JUnit用一个
Statement
来做把setUp()
,test1()
,以及tearDown()
封装到一起,并保证其执行顺序。
References
Java Annotation
http://www.cnblogs.com/mandroid/archive/...BlockJUnit4ClassRunner
http://grepcode.com/file/repo1.maven.org...TestClass::getAnnotatedMethods()
http://grepcode.com/file/repo1.maven.org...
下期内容
BlockJUnit4ClassRunner
又被谁调用了呢?
运行unit test的入口在哪里?
请看:[深入JUnit] 测试运行的入口
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。