若是咱們測試知道這個方法是要拋出異常纔是咱們所指望的,否則就是測試失敗,咱們要如何驗證呢?驗證碼完成一般是重要的,可是確保代碼在特殊狀況下的行爲(如:異常,狀態,超時,etc)一樣重要。 舉個例子:java
new ArrayList<Object>().get(0);
這無疑無拋出IndexOutOfBoundsException,簡稱IOOBE。在@Test註解中,存在一個excepted參數,能夠知道方法會拋出咱們預期的異常。若是咱們想去驗證ArraryList 拋出正確的異常,咱們能夠這樣寫:單元測試
@Test(expected = IndexOutOfBoundsException.class) public void empty() { new ArrayList<Object>().get(0); }
這個excepted 參數應該是咱們所應該關心的,若是這個執行方法拋出IOOBE,那麼這個方法將會經過測試。是否是用起來很簡單,很爽。然而,這個方法並非如理想中那麼簡單,萬能的。其實官方推薦的是使用 ExceptedException rule, 來實現。測試
下面我舉一個比較極端的一個例子吧! 若是我要測試一個方法,我碰見他會是超時的,終會拋出超時異常: 咱們能夠這樣寫:ui
@Test(timeout = 1000,expected = TestTimedOutException.class) public void testA() { System.out.println("first"); for (;;){}// 必然會拋出超時異常 }
我預測,他終會拋出異常超時,可是它仍然是沒法經過測試的,這樣的狀況咱們要如何作呢? 好吧,咱們就試試project B, 按照官方推薦的試試:this
@Rule public ExpectedException thrown = ExpectedException.none(); @Test(timeout = 1000) public void testB() { thrown.expect(TestTimedOutException.class); for(;;){} }
這樣就能無缺的經過測試。固然,@Test(timeout=1000) 也是能夠用** @Rule public Timeout globalTimeout = Timeout.seconds(1000); ** 來替代的,後面會講到,你們耐心一點哈!.net
上面的方法對簡單的狀況頗有用,但也有它的侷限性。例如,您不能在異常中測試消息的值,或者在拋出異常後對域對象的狀態進行測試(如訂單業務的 下單狀態、支付狀態、退款狀態這種比較常見),etc。rest
在JUnit3.x 是經過 Try/Catch 來實現的code
@Test public void testExceptionMessage() { try { new ArrayList<Object>().get(0); fail("Expected an IndexOutOfBoundsException to be thrown"); } catch (IndexOutOfBoundsException anIndexOutOfBoundsException) { assertThat(anIndexOutOfBoundsException.getMessage(), is("Index: 0, Size: 0")); } }
另外,使用ExpectedException rule . 此規則不只能夠指示您指望的異常狀況,還能夠指示預期的異常消息:對象
@Rule public ExpectedException thr = ExpectedException.none(); @Test public void shouldTestExceptionMessage() throws IndexOutOfBoundsException { List<Object> list = new ArrayList<Object>(); // 預測異常 thr.expect(IndexOutOfBoundsException.class); thr.expectMessage("Index: 0, Size: 0"); list.get(0); // execution will never get past this line }
也可讓你的expectmessage使用匹配器,這使你在你的測試更多的靈活性。一個例子:blog
thrown.expectMessage(Matchers.containsString("Size: 0"));
引入匹配器,須要org.hamcrest 的jar 包。 此外,您可使用匹配檢查異常,若是它具備嵌入式狀態你想驗證。例如:
import static org.hamcrest.Matchers.hasProperty; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.startsWith; import javax.ws.rs.NotFoundException; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; 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(NotFoundException.class); thrown.expectMessage(startsWith("some Message")); thrown.expect(hasProperty("response", hasProperty("status", is(404)))); testThing.chuck(); } private class TestThing { public void chuck() { Response response = Response.status(Status.NOT_FOUND).entity("Resource not found").build(); throw new NotFoundException("some Message", response); } } }