单元测试用于验证一段代码是否按照开发人员的预期运行。 有时,这意味着检查代码是否也会引发预期的异常。 JUnit是Java单元测试的标准,并提供了几种验证抛出异常的机制。 本文探讨了这些选项及其相对优点。以下面的简单代码段为例。 除了编写测试以确保canVote()方法返回true或false之外,您还应该编写测试以验证是否在期望时抛出IllegalArgumentException
。
java">public class Student {
public boolean canVote(int age) {
if (i<=0) throw new IllegalArgumentException("age should be +ve");
if (i<18) return false;
else return true;
}
}
(番石榴前提条件可能更适合于这些参数检查,但该示例仍然有效)。
有3种常见的方法可以检查是否引发了异常,每种方法都有其自身的优缺点。
1)@Test(预期...)
@Test批注具有一个可选参数“ expected”,该参数允许您指定Throwable的子类。 如果我们想验证上面的canVote()
()方法抛出正确的异常,我们将编写:
java">@Test(expected = IllegalArgumentException.class)
public void canVote_throws_IllegalArgumentException_for_zero_age() {
Student student = new Student();
student.canVote(0);
}
简单明了(如果有点不精确),因为它测试将异常抛出到方法的某个地方,而不是放在特定的行上。
2)ExpectedException
要使用JUnit的ExpectedException ,首先需要声明ExpectedException:
java">@Rule
public ExpectedException thrown= ExpectedException.none();
然后,您可以使用仅指定预期异常的更简单方法:
java">@Test
public void canVote_throws_IllegalArgumentException_for_zero_age() {
Student student = new Student();
thrown.expect(NullPointerException.class);
student.canVote(0);
}
或者也可以指定预期的异常消息:
java">@Test
public void canVote_throws_IllegalArgumentException_for_zero_age() {
Student student = new Student();
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("age should be +ve");
student.canVote(0);
}
除了可以指定预期的异常消息之外,此ExpectedException方法还具有使您可以更精确地了解预期将在何处引发异常的优点。 在上面的示例中,在构造函数中引发意外的IllegalArgumentException会导致测试失败,因为我们希望测试能够在canVote()方法中引发。
附带说明一下,如果不需要声明,那就太好了:
java">@Rule public ExpectedException thrown= ExpectedException.none();
好像是不必要的噪音。 能够做的很好
java">expect(RuntimeException.class)
要么
java">expect(RuntimeException.class, “Expected exception message”)
或至少能够在一次对ExpectedException的调用中传递异常和消息:
java">thrown.expect(IllegalArgumentException.class, “age should be +ve”);
3)尝试/抓住断言/失败
在JUnit4之前,检查异常的方法是使用try / catch块。
java">@Test
public void canVote_throws_IllegalArgumentException_for_zero_age() {
Student student = new Student();
try {
student.canVote(0);
} catch (IllegalArgumentException ex) {
assertThat(ex.getMessage(), containsString("age should be +ve"));
}
fail("expected IllegalArgumentException for non +ve age");
}
尽管这是一种较旧的方法,但仍然完全有效。 主要缺点是,很容易忘记将fail()放在catch后面,如果未引发预期的异常,则会导致误报。 我过去肯定犯了这个错误!
总之,有三种主要的方法可以测试预期的异常,每种方法都有其自身的优缺点。 就我个人而言,由于它的精确度和测试异常消息的能力,我通常倾向于ExpectedException方法。
翻译自: https://www.javacodegeeks.com/2014/02/testing-for-expected-exceptions-in-junit.html