在Junit中处理异常的方式有很多种,比如:
有人推荐我尝试一下catch-exception,在这篇文章中我将会向大家介绍。简而言之,catch-exception库可以仅在一行代码中捕获异常,以后再对其进行处理。
通过Maven安装
com.googlecode.catch-exception
catch-exception
1.2.0
test
依存关系树如下:
[INFO] --- maven-dependency-plugin:2.1:tree @ unit-testing-demo ---
[INFO] com.github.kolorobot:unit-testing-demo:jar:1.0.0-SNAPSHOT
[INFO] +- org.slf4j:slf4j-api:jar:1.5.10:compile
[INFO] +- org.slf4j:jcl-over-slf4j:jar:1.5.10:runtime
[INFO] +- org.slf4j:slf4j-log4j12:jar:1.5.10:runtime
[INFO] +- log4j:log4j:jar:1.2.15:runtime
[INFO] +- junit:junit:jar:4.11:test
[INFO] +- org.mockito:mockito-core:jar:1.9.5:test
[INFO] +- org.assertj:assertj-core:jar:1.5.0:test
[INFO] +- org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] +- org.hamcrest:hamcrest-library:jar:1.3:test
[INFO] +- org.objenesis:objenesis:jar:1.3:test
[INFO] \- com.googlecode.catch-exception:catch-exception:jar:1.2.0:test
准备开始
被测系统(SUT):
class ExceptionThrower {
void someMethod() {
throw new RuntimeException("Runtime exception occurred");
}
void someOtherMethod() {
throw new RuntimeException("Runtime exception occurred",
new IllegalStateException("Illegal state"));
}
void yetAnotherMethod(int code) {
throw new CustomException(code);
}
}
使用AssertJ断言的BDD-style方法catch-exception示例:
import org.junit.Test;
import static com.googlecode.catchexception.CatchException.*;
import static com.googlecode.catchexception.apis.CatchExceptionAssertJ.*;
public class CatchExceptionsTest {
@Test
public void verifiesTypeAndMessage() {
when(new SomeClass()).someMethod();
then(caughtException())
.isInstanceOf(RuntimeException.class)
.hasMessage("Runtime exception occurred")
.hasMessageStartingWith("Runtime")
.hasMessageEndingWith("occured")
.hasMessageContaining("exception")
.hasNoCause();
}
}
看起来不错——简单,可读性高。没有JUnit运行。请注意,我指定的那个在SomeClass类中抛出异常的方法。可想而知,我可以在一个测试中检验多个异常。但是这违背了测试中的单一任务原则,所以不推荐这种做法。另外,如果你是用Eclipse工作的话,也许这篇文章对你有用。
检查异常的原因
我相信下面的代码就没有必要讨论了吧:
import org.junit.Test;
import static com.googlecode.catchexception.CatchException.*;
import static com.googlecode.catchexception.apis.CatchExceptionAssertJ.*;
public class CatchExceptionsTest {
@Test
public void verifiesCauseType() {
when(new ExceptionThrower()).someOtherMethod();
then(caughtException())
.isInstanceOf(RuntimeException.class)
.hasMessage("Runtime exception occurred")
.hasCauseExactlyInstanceOf(IllegalStateException.class)
.hasRootCauseExactlyInstanceOf(IllegalStateException.class);
}
}
使用Hamcrest来检查自定义异常
为了检查自定义异常,我用了在之前的文章中谈到的Hamcrest匹配代码。
class CustomException extends RuntimeException {
private final int code;
public CustomException(int code) {
this.code = code;
}
public int getCode() {
return code;
}
}
class ExceptionCodeMatches extends TypeSafeMatcher {
private int expectedCode;
public ExceptionCodeMatches(int expectedCode) {
this.expectedCode = expectedCode;
}
@Override
protected boolean matchesSafely(CustomException item) {
return item.getCode() == expectedCode;
}
@Override
public void describeTo(Description description) {
description.appendText("expects code ")
.appendValue(expectedCode);
}
@Override
protected void describeMismatchSafely(CustomException item, Description mismatchDescription) {
mismatchDescription.appendText("was ")
.appendValue(item.getCode());
}
}
测试部分:
import org.junit.Test;
import static com.googlecode.catchexception.CatchException.*;
import static org.junit.Assert.*;
public class CatchExceptionsTest {
@Test
public void verifiesCustomException() {
catchException(new ExceptionThrower(), CustomException.class).yetAnotherMethod(500);
assertThat((CustomException) caughtException(), new ExceptionCodeMatcher(500));
}
}
总结
catch-exception看起来很棒,上手非常简单。比起在JUnit中的方法它具有很多优势。如果有机会我竟会深入的研究一下这个库,希望在现实中能有一个这样的机会。
如果你感兴趣,可以看一下我其他的文章:
javacodegeeks 翻译:
ImportNew.com -
赖 信涛
译文链接:
http://www.importnew.com/10922.html
[
转载请保留原文出处、译者和译文链接。]