單元測試這一塊咱們一直都有在接觸,可是對於我來講,還不夠重視或深刻,能夠說是忽視的一塊,如今公司要把測試覆蓋率給推起來,此時正好能夠來探究探究。 JUnit4 單元測試主要有如下的一些功能:html
注意:本版本基於JUnit4.12。java
下面咱們會對這樣的一個類作參數測試,咱們需呀一個 參數 和 一個預期結果值git
public class Fibonacci { public static int compute(int n) { int result = 0; if (n <= 1) { result = n; } else { result = compute(n - 1) + compute(n - 2); } return result; } }
如何作測試?第一個方法是構造函數方式github
@RunWith(Parameterized.class) public class FibonacciTest { @Parameters public static Collection<Object[]> data() { /* 數組第一個 爲 參數, 第二個爲 指望結果 */ return Arrays.asList(new Object[][] {{0, 0}, {1, 1}, {2, 1}, {3, 2}, {4, 3}, {5, 5}, {6, 8}}); } private int fInput; private int fExpected; public FibonacciTest(int input, int expected) { fInput = input; fExpected = expected; } @Test public void test() { Assert.assertEquals(fExpected, Fibonacci.compute(fInput)); } }
非構造函數實現(推薦:非構造函數更加靈活,不會影響類的其餘方法):數組
@RunWith(Parameterized.class) public class FibonacciTest2 { @Parameters public static Collection<Object[]> data() { return Arrays.asList(new Object[][] {{0, 0}, {1, 1}, {2, 1}, {3, 2}, {4, 3}, {5, 5}, {6, 8}}); } @Parameter // first data value (0) is default public /* NOT private */ int fInput; // 數組第一個參數爲輸入參數 @Parameter(1) public /* NOT private */ int fExpected; // 數組第一個參數爲 預期參數 @Test public void test() { Assert.assertEquals(fExpected, Fibonacci.compute(fInput)); } }
參考:https://github.com/junit-team/junit4/wiki/Parameterized-tests函數
在咱們編寫測試用例的過程當中,咱們每每都會有指望異常的測試方法,有異常就是對了。 舉一個例子單元測試
new ArrayList<Object>().get(0);
這樣的方法毫無疑問會爆出IndexOutOfBoundsException 數組越界異常,爲此,咱們要驗證這個異常的出現是正確的,咱們能夠@Test(exceted=IndexOutOfBoundsException.class) 來標記指望的異常。測試
@Test(expected = IndexOutOfBoundsException.class) public void empty() { new ArrayList<Object>().get(0); }
然而這個只是方法之一,但卻不是推薦的方法,對於更長的測試,建議使用ExpectedException Rule 來實現;ui
對異常進行更深的測試: 上面的方式是一個很是好的示例,可是他是有限制的。例如, 不能在異常中測試消息的值, 也不能在引起異常後檢測域對象的狀態。在Junit3.x 是用 try/catch 來作的(這個不浪費時間敘述),可是在Junit4.x 可使用 @Rule 來實現。使用 ExpectedException 規則。此規則容許您不只指示所指望的異常, 並且還能夠顯示所指望的異常消息。 實現以下:this
public class TestExyRule { @Rule public ExpectedException thrown = ExpectedException.none(); @Test public void shouldTestExceptionMessage() throws IndexOutOfBoundsException { List<Object> list = new ArrayList<Object>(); thrown.expect(IndexOutOfBoundsException.class); thrown.expectMessage("Index: 0, Size: 0"); list.get(0); // execution will never get past this line } }
上面例子的expectMessage 可使用 Matchers 來作, 這樣能夠更加的靈活,如:thrown.expectMessage(Matchers.containsString("Size: 0")); 固然咱們也能夠更加進一步的 驗證異常的狀態:
import static org.hamcrest.Matchers.hasProperty; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.startsWith; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; public class TestExy { @Rule public ExpectedException thrown = ExpectedException.none(); @Test public void shouldThrow() { TestThing testThing = new TestThing(); thrown.expect(UnsupportedOperationException.class); thrown.expectMessage(startsWith("some Message")); testThing.chuck(); } private class TestThing { public void chuck() { throw new UnsupportedOperationException("some Message"); } } }
https://github.com/junit-team/junit4/wiki/Exception-testing
https://github.com/junit-team/junit4/wiki/Timeout-for-tests 超時測試比較簡單,舉個例子。
@Test(timeout =1000) public void testMethod() { for(;;){} }
如上面的代碼咱們對時間作了限制爲1s, 可是因爲有死循環,是沒法在規定時間內經過測試的。
https://github.com/junit-team/junit4/wiki/Aggregating-tests-in-suites
https://github.com/junit-team/junit4/wiki/Categories