JUnit 4 - 期望某个类的异常,但不是子类

  • 本文关键字:异常 子类 期望 JUnit java junit
  • 更新时间 :
  • 英文 :


我将尝试提供一个陈词滥调,无用的例子,很好地减少问题:-)

我有一个GenericException,和一个延伸GenericExceptionMoreSpecificException

我需要测试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.如果它抛出MoreSpecificExceptionGenericException的任何其他子类,我希望测试失败。

阅读文档时,我似乎无法对注释做任何事情来更改此行为,因此看起来我将不得不使用另一种解决方案。

目前,我正在采用以下丑陋的解决方案 - 内森休斯的回答使编辑变得不那么丑陋:-)

@Test
public void testDoThat() {
    try {
        new SomeService().doThat();
        Assert.fail();
    } catch(GenericException ex) {
        Assert.assertEquals(GenericException.class, ex.getClass());
    }
}

在 JUnit 框架中,有没有更优雅的方式来实现我想要的东西?

BDD 样式解决方案

JUnit 4 + 捕获异常 + 断言J

最优雅的解决方案;)可读,无样板代码。

@Test
public void testDoThat() {
    when(new SomeService()).doThat();
    then(caughtException()).isExactlyInstanceOf(GenericException.class);
}

对于 FEST 断言 2 + 捕获异常,代码是相同的。

源代码

  • https://gist.github.com/mariuszs/7489706

依赖

org.assertj:assertj-core:1.4.0
com.googlecode.catch-exception:catch-exception:1.2.0

您可以断言异常的类是您所期望的:

@Test
public void testDoThat() {
    try {
        new SomeService().doThat();
        Assert.fail();
    } catch(GenericException ex) {
        assertEquals(GenericException.class, ex.getClass());
    }
}

还摆脱了标志,而是在没有抛出异常的情况下让测试失败。

可以使用

ExpectException 规则和指定可以抛出哪个类的自定义 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);
   }
}

编辑:添加静态工厂方法以使测试代码更清晰。

最新更新