使用自定义字段中的特定条件断言预期异常
Assert expected exception with specific criteria in custom fields
我想验证预期异常是否满足特定条件。以此为出发点:
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 匹配器检查对象的任意字段。
您可以使用 TypeSafeMatcher
,其中您可以提供 MyException
class,然后 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));
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
添加更多匹配器,而且感觉更像一种构建可组合匹配器的“规范”方法,允许您为测试用例构建所需的精确匹配器。
一种简洁明了的替代方法是使用 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");
我想验证预期异常是否满足特定条件。以此为出发点:
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 匹配器检查对象的任意字段。
您可以使用 TypeSafeMatcher
,其中您可以提供 MyException
class,然后 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));
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
添加更多匹配器,而且感觉更像一种构建可组合匹配器的“规范”方法,允许您为测试用例构建所需的精确匹配器。
一种简洁明了的替代方法是使用 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");