代码之家  ›  专栏  ›  技术社区  ›  DodgyCodeException

在自定义字段中使用特定条件断言预期异常

  •  0
  • DodgyCodeException  · 技术社区  · 4 年前

    我想验证预期的异常是否符合某些标准。以此为起点:

    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匹配器检查对象的任意字段。

    0 回复  |  直到 4 年前
        1
  •  3
  •   Klitos Kyriacou    4 年前

    一个深思熟虑且简洁的替代方法是使用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");
    
        2
  •  1
  •   Lino    4 年前

    您可以使用 TypeSafeMatcher 您可以在哪里提供您的 MyException 类,然后a 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));
    
        3
  •  1
  •   Taner Md. Arafat Hasan    2 年前

    还有 FeatureMatcher 在Hamcrest中,这非常适合为对象的嵌套“特征”创建匹配器。因此,在您的示例中,您可以使用 功能修补器 按照以下方式(这是我在为嵌套字段创建匹配器时倾向于遵循的模式):

    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 这感觉像是一种更“规范”的方法来构建可组合的匹配器,允许您为测试用例构建所需的精确匹配器。