Java中測試異常的多種方式


使用JUnit來測試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方法。

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"));  }   } 

這是最容易想到的一種方式,但是太啰嗦。

JUnit annotation方式

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

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

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

ExpectedException rule

JUnit7以后提供了一個叫做ExpectedException的Rule來實現對異常的測試。

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);   } 

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

使用catch-exception庫

有個catch-exception庫也可以實現對異常的測試。

首先引用該庫。

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()));  } 

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM