Утверждение ожидаемого исключения с указанными c критериями в пользовательских полях - PullRequest
1 голос
/ 21 января 2020

Я хочу убедиться, что ожидаемое исключение соответствует определенным критериям. Возьмем это как отправную точку:

class MyException extends RuntimeException {
    int n;
    public MyException(String message, int n) {
        super(message);
        this.n = n;
    }
}

public class HowDoIDoThis {
    @Rule
    public ExpectedException thrown = ExpectedException.none();

    @Test
    public void test1() {
        thrown.expect(MyException.class);
        throw new MyException("x", 10);
    }
}

Как я могу утверждать, например, что выброшенное исключение имеет n > 1, а message содержит только строчные буквы? Я думал об использовании thrown.expect(Matcher), но не могу понять, как заставить совпадение Hamcrest проверять произвольные поля объекта.

Ответы [ 3 ]

1 голос
/ 29 января 2020

В Hamcrest также есть FeatureMatcher, который отлично подходит для создания сопоставителей для вложенных «функций» объектов. Итак, в вашем примере вы можете структурировать его, используя FeatureMatcher следующим образом (это шаблон, которому я склонен следовать при создании сопоставлений для вложенных полей):

public final class MyExceptionMatchers {

    public static Matcher<MyException> withNthat(Matcher<Integer> nMatcher) {
        return new FeatureMatcher<MyException, Integer>(nMatcher, "n", "n") {
              @Override
              protected Integer featureValueOf(MyException actual) {
                   return actual.n;
              }
        }
    }
}

И в вашем тесте:

import static x.y.z.MyExceptionMatchers.withNthat;
import static org.hamcrest.Matchers.greaterThan;

...

thrown.expect(withNThat(greaterThan(1)));

С этим макетом очень просто добавить больше совпадений для MyException, и это похоже на более "канонический" подход к созданию составных сопоставлений, которые позволяют вам создать точное совпадение, которое вы хотите для своего тестового примера.

1 голос
/ 21 января 2020

Вы можете использовать TypeSafeMatcher, где вы можете указать свой класс MyException, а затем IntPredicate, чтобы проверить значение n по условию:

public class MyExceptionMatcher extends TypeSafeMatcher<MyException> {
    private final IntPredicate predicate;

    public MyExceptionMatcher(IntPredicate predicate) {
        this.predicate = predicate;
    }

    @Override
    protected boolean matchesSafely(MyException item) {
        return predicate.test(item.n);
    }

    @Override
    public void describeTo(Description description) {
        description.appendText("my exception which matches predicate");
    }
}

Тогда вы можете ожидать, как итак:

thrown.expect(new MyExceptionMatcher(i -> i > 1));
0 голосов
/ 30 января 2020

Краткий и удобный альтернативный способ - использовать AssertJ вместо правила ExpectedException.

    assertThatThrownBy(() -> {
        throw new MyException("x", 10);
    })
        .matches(e -> e.getMessage().equals(e.getMessage().toLower()), "message is lowercase")
        .matches(e -> ((CustomException) e).n > 10, "n > 10");
...