我会尝试提供一个陈腐,无用的例子来很好地减少问题: - )
我有一个GenericException
,一个MoreSpecificException
扩展了GenericException
。
我需要测试SomeService.doThis()
是否会引发MoreSpecificException
。 JUnit让我这样优雅。
@Test(expected = MoreSpecificException.class)
public void testDoThis() throws GenericException {
new SomeService().doThis();
}
但是,我还需要测试SomeService.doThat()
是否会引发GenericException
,所以我试过了。
@Test(expected = GenericException.class)
public void testDoThat() throws GenericException {
new SomeService().doThat();
}
然而,我发现如果doThat()
实际上抛出MoreSpecificException
,那么第二次测试仍会通过。我认为这是因为MoreSpecificException
是 GenericException
并且实施了注释以尊重该关系。
虽然这是一个合理的默认行为,我不想要这个。我想测试doThat()
只引用GenericException
而仅引发GenericException
。如果它抛出MoreSpecificException
或GenericException
的任何其他子类,我希望测试失败。
阅读docs我似乎无法使用注释来改变这种行为,所以看起来我将不得不使用另一种解决方案。
目前我正在采取以下丑陋的解决方案 - 编辑使得Nathan Hughes的回答明显减少了: - )
@Test
public void testDoThat() {
try {
new SomeService().doThat();
Assert.fail();
} catch(GenericException ex) {
Assert.assertEquals(GenericException.class, ex.getClass());
}
}
在JUnit框架中有更优雅的方式来实现我想要的东西吗?
答案 0 :(得分:3)
您可以断言Exception的类是您所期望的:
@Test
public void testDoThat() {
try {
new SomeService().doThat();
Assert.fail();
} catch(GenericException ex) {
assertEquals(GenericException.class, ex.getClass());
}
}
同样摆脱了标志,如果没有抛出异常,则测试失败。
答案 1 :(得分:3)
最优雅的解决方案;)可读,没有样板代码。
@Test
public void testDoThat() {
when(new SomeService()).doThat();
then(caughtException()).isExactlyInstanceOf(GenericException.class);
}
FEST Assertions 2 + Catch-Exceptions的代码相同。
org.assertj:assertj-core:1.4.0
com.googlecode.catch-exception:catch-exception:1.2.0
答案 2 :(得分:1)
您可以使用ExpectedException规则和自定义Hamcrest匹配器来指定可以抛出哪个类。
以下测试将打印您期望的RuntimeException实例,但是得到了IllegalArgumentException。
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
public void testThrows() {
thrown.expect(isClass(RuntimeException.class));
throw new IllegalArgumentException("FAKE");
}
public class ClassMatchMatcher extends BaseMatcher<Object> {
private final Class<?> expectedClass;
private ClassMatchMatcher(Class<?> expectedClass) {
this.expectedClass = expectedClass;
}
@Override
public boolean matches(Object item) {
return expectedClass.equals(item.getClass());
}
@Override
public void describeTo(Description description) {
description.appendText("an instance of ")
.appendText(expectedClass.getName());
}
}
public class ExtraMatchers {
public static Matcher<Object> isClass(Class<?> aClass) {
return new ClassMatchMatcher(aClass);
}
}
编辑:添加了一个静态工厂方法,以使测试代码更清晰。