匹配自定义异常

Matching custom exceptions

Javadocmatches 方法给出了这个例子:

assertThat(player).matches(p -> p.isRookie());

确实,当我定义一个虚拟 class Player 时,上面的语句编译正常。但是,当我定义一个派生自 Exception 的 class 时,以下内容不会编译:

public class MyCustomException extends Exception {
    public boolean isMyCustomFieldSet() { return true; }
}
...
MyCustomException myCustomException = new MyCustomExcpetion();
assertThat(myCustomException).matches(e -> e.isMyCustomFieldSet());

我可以使用强制转换使其编译:

assertThat(myCustomException).matches(e -> ((MyCustomException)e).isMyCustomFieldSet());

但该演员表看起来 "ugly" 并且有点破解以解决某种缺陷。我可以让它以 "nicer" 方式编译,即不使用强制转换吗?

我认为你找不到更短的路。

问题是

assertThat(new Player())

returns 一个 ObjectAssert<Player>,其 matches 签名为 matches(Predicate<? super Player>)

然而,

assertThat(new MyException())

实际上调用了一个不同的方法 assertThat,其中 returns 一个 AbstractThrowableAssert<?, ? extends Throwable> 和一个 matches(Predicate<? super Throwable>).

这就解释了问题,但我无法为您提供更好的解决方法。

我还没有检查是否存在针对它的未解决问题,但如果不存在,可能值得提交一个。

据我所知,无法直接使用方法 isMyCustomFieldSet。因为使用泛型 class 和泛型 class 的断言库不能直接或间接扩展 Throwable class。 More info here

问题出在 Assertions,它声明 AbstractThrowableAssert<?, ? extends Throwable> assertThat(Throwable t) 而不是 <T> AbstractThrowableAssert<?, T extends Throwable> assertThat(T t)

但不幸的是,由于以下现有方法与之冲突,因此无法完成此操作:public static <T> ObjectAssert<T> assertThat(T actual)

铸造是一种解决方案,我同意它不是超级优雅。

在那种情况下我会做的很简单:

assertThat(myCustomException.isMyCustomFieldSet()).isTrue();

或直接对 myCustomException 进行断言:

assertThat(myCustomException).hasFieldOrPropertyWithValue("myCustomFieldSet", true)
                             .hasFieldOrPropertyWithValue("myOtherField", "foo");

这里的缺点是按名称访问字段,这对重构不友好。