Java中測試異常的多種方式

使用JUnit來測試Java代碼中的異常有不少種方式,你知道幾種?java

給定這樣一個class。測試

Person.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class Person {   private String name;  private int age;   public String getName() {  return name;  }   public void setName(String name) {  this.name = name;  }   public int getAge() {  return age;  }   public void setAge(int age) {   if (age < 0 ) {  throw new IllegalArgumentException("age is invalid");  }  this.age = age;  } } 

咱們來測試setAge方法。this

Try-catch 方式

1
2
3
4
5
6
7
8
9
10
11
 @Test  public void shouldGetExceptionWhenAgeLessThan0() {  Person person = new Person();  try {  person.setAge(-1);  fail("should get IllegalArgumentException");  } catch (IllegalArgumentException ex) {  assertThat(ex.getMessage(),containsString("age is invalid"));  }   } 

這是最容易想到的一種方式,可是太囉嗦。google

JUnit annotation方式

JUnit中提供了一個expected的annotation來檢查異常。spa

1
2
3
4
5
6
 @Test(expected = IllegalArgumentException.class)  public void shouldGetExceptionWhenAgeLessThan0() {  Person person = new Person();  person.setAge(-1);   } 

這種方式看起來要簡潔多了,可是沒法檢查異常中的消息。rest

ExpectedException rule

JUnit7之後提供了一個叫作ExpectedException的Rule來實現對異常的測試。code

1
2
3
4
5
6
7
8
9
10
11
12
 @Rule  public ExpectedException exception = ExpectedException.none();   @Test  public void shouldGetExceptionWhenAgeLessThan0() {   Person person = new Person();  exception.expect(IllegalArgumentException.class);  exception.expectMessage(containsString("age is invalid"));  person.setAge(-1);   } 

這種方式既能夠檢查異常類型,也能夠驗證異常中的消息。xml

使用catch-exception庫

有個catch-exception庫也能夠實現對異常的測試。get

首先引用該庫。it

pom.xml
1
2
3
4
5
6
 <dependency>  <groupId>com.googlecode.catch-exception</groupId>  <artifactId>catch-exception</artifactId>  <version>1.2.0</version>  <scope>test</scope> <!-- test scope to use it only in tests -->  </dependency> 

而後這樣書寫測試。

1
2
3
4
5
6
7
8
 @Test  public void shouldGetExceptionWhenAgeLessThan0() {  Person person = new Person();  catchException(person).setAge(-1);  assertThat(caughtException(),instanceOf(IllegalArgumentException.class));  assertThat(caughtException().getMessage(), containsString("age is invalid"));   } 

這樣的好處是能夠精準的驗證異常是被測方法拋出來的,而不是其它方法拋出來的。

catch-exception庫還提供了多種API來進行測試。

先加載fest-assertion庫。

1
2
3
4
5
 <dependency>  <groupId>org.easytesting</groupId>  <artifactId>fest-assert-core</artifactId>  <version>2.0M10</version>  </dependency> 

而後能夠書寫BDD風格的測試。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
 @Test  public void shouldGetExceptionWhenAgeLessThan0() {  // given  Person person = new Person();   // when  when(person).setAge(-1);   // then  then(caughtException())  .isInstanceOf(IllegalArgumentException.class)  .hasMessage("age is invalid")  .hasNoCause();  } 

若是喜歡Hamcrest風格的驗證風格的話,catch-exception也提供了相應的Matcher API。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
 @Test  public void shouldGetExceptionWhenAgeLessThan0() {  // given  Person person = new Person();   // when  when(person).setAge(-1);   // then  assertThat(caughtException(), allOf(  instanceOf(IllegalArgumentException.class)  , hasMessage("age is invalid")  ,hasNoCause()));  } 

第一種最土鱉,第二種最簡潔,第四種最靠譜。

相關文章
相關標籤/搜索