最近对JUnit和Mockito的内部实现比较感兴趣,将在接下来的一段时间,和你们一块儿深刻代码细节。html
王侯将相,宁有种乎 (JUnit也没啥Magic吧)java
阅读前提android
据说过Java Annotationsegmentfault
使用过JUnitmaven
知道@Before, @After, @Test
ide
对JUnit的内部实现有兴趣函数
代码版本: junit 4.12
代码搜索工具: http://grepcode.com/
经常使用符号工具
_
: 用来略去代码段中可有可无的parameter测试
...
: 用来略去可有可无的代码实现spa
下面是一个很简单的JUunit Test Class
public class SampleTest { @Before protected void setUp(){ ... } @Test public void test1(){ ... } @After public void tearDown(){ ... } }
本文要解答的问题:@Before
, @Test
, @After
如何影响test workflow的?
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是什么。
利用Java原生的getDeclaredAnnotations
和getDeclaredMethods
,能够轻松地获得测试类SampleTest中函数的annotations。
JUnit用一个Statement
来作把setUp()
,test1()
,以及tearDown()
封装到一块儿,并保证其执行顺序。
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] 测试运行的入口