assertThatThrownBy() 检查自定义异常的字段

assertThatThrownBy() check field on custom exception

如何使用 assertJ 检查自定义异常中的特定字段值?

这里是例外 class:

public class SomeException extends RuntimeException {
    private final Set<Integer> something;

    public SomeException (String message, Set<Integer> something) {
        super(message);

        this.something = something;
    }

    public Set<Integer> getSomething() {
        return something;
    }
}

这是我的测试:

    assertThatThrownBy(() -> service.doSomething())
        .isInstanceOf(SomeException.class)
        .hasMessageStartingWith("SomeException has 1,2,3,4 in something field. I want assert that")
        . ??? check that SomeException.getSomething() has 1,2,3,4 ???

问题是,如果我链接 extracting(),它会认为我正在使用 Throwable。所以我无法提取 field something

更新:

SomeException throwable = (SomeException) catchThrowable(() -> service.doSomething(

assertThat(throwable)
    .hasMessageStartingWith("extracting() bellow still think we're working with Throwable")
    .extracting(SomeException::getSomething <<<--- doesn't work here)

我已尝试按照以下建议进行操作:

 assertThat(throwable)
        .hasMessageStartingWith("Works except containsExactlyInAnyOrder()")
        .asInstanceOf(InstanceOfAssertFactories.type(SomeException.class))
        .extracting(SomeException::getSomething)
        .->>>containsExactlyInAnyOrder<<<--- Not working!!!

但我不能再使用 containsExactlyInAnyOrder() :(

请指教

extracting 有很多变体,您要使用的是 extracting(String),例如:

   assertThatThrownBy(() -> service.doSomething())
        .isInstanceOf(SomeException.class)
        .hasMessageStartingWith("SomeException ... ")
        .extracting("something")
        .isEqualTo(1,2,3,4);

使用 extracting(String, InstanceOfAssertFactory) 获得专门的断言,因此如果值是一个集合,您可以尝试:

   assertThatThrownBy(() -> service.doSomething())
        .isInstanceOf(SomeException.class)
        .hasMessageStartingWith("SomeException ... ")
        .extracting("something", InstanceOfAssertFactories.ITERABLE)
        .contains();

你也可以试试:hasFieldOrPropertyWithValue

更新: 工作示例

SomeException throwable = new SomeException("foo", Sets.newSet(1, 2, 3, 4));

assertThat(throwable).hasMessageStartingWith("fo")
                     .extracting("something", InstanceOfAssertFactories.ITERABLE)
                     .containsExactly(1, 2, 3, 4);

我会做类似的事情:

assertThatThrownBy(() -> service.doSomething())
    .isInstanceOf(SomeException.class)
    .hasMessageStartingWith("SomeException occurred")
    .isEqualToComparingFieldByField(
        new SomeException("", Sets.newHashSet(1,2,3,4)));

这样您就不必担心将来会更改字段名称,因为您不会在断言语句中的任何地方对其进行硬编码。

您似乎在寻找 catchThrowableOfType,它可以让您收到正确的 class:

import static org.assertj.core.api.Assertions.catchThrowableOfType;

SomeException throwable = catchThrowableOfType(() -> service.doSomething(), SomeException.class);

assertThat(throwable.getSomething()).isNotNull();