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

第一种最土鳖,第二种最简洁,第四种最靠谱。

相关文章
相关标签/搜索