最近對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] 測試運行的入口