首页 > 解决方案 > 如何创建 ArchUnit 规则来验证抛出的所有异常都继承自特定的自定义异常?

问题描述

我的架构规则之一是应用程序代码抛出的所有异常必须是 CustomException 或 CustomException 的子类。

我在 ArchUnit 中编写这条规则时遇到了困难。我目前拥有的是以下内容:

private static final ArchCondition<JavaClass> THROWS_NON_CUSTOM_EXCEPTION = callCodeUnitWhere( 
   target(is(constructor()))
      .and(
         originOwner(
            is(assignableTo(Throwable.class)) 
            .and(not(assignableTo(CustomException.class)))
         )
      )
   );

@ArchTest public static final ArchRule noNonCustomExceptions = noClasses()
   .should(THROWS_NON_CUSTOM_EXCEPTION);

运行此规则会返回 true(JUnit 测试通过),即使我的代码会引发不是 CustomException 的异常。

我已经测试了检测构造函数具有可分配给 Throwable 的所有者的规则部分:

private static final ArchCondition<JavaClass> THROWS_NON_CUSTOM_EXCEPTION =    
   callCodeUnitWhere( 
      target(is(constructor()))
         .and(
            originOwner( 
               is(assignableTo(Throwable.class))
            )
         )
   );

这会正确返回代码中创建任何 Throwable 的每个位置。

问题似乎出在我的代码中,它试图找到不可分配给 CustomException 的所有者:

   private static final ArchCondition<JavaClass> THROWS_NON_CUSTOM_EXCEPTION = callCodeUnitWhere( 
      target(is(constructor()))
         .and(
            originOwner( 
               is(not(assignableTo(CustomException.class)))
            )
         )
   );

这将返回每个构造函数,即使是那些可分配给 CustomException 的异常。

ArchUnit 中编写规则的正确方法是什么,该规则返回调用构造函数的每个代码单元,该构造函数的所有者可分配给 Throwable,而不是可分配给 CustomException?

标签: javaunit-testingarchunit

解决方案


我认为你只需要结合你已经拥有的部分。以下代码适用于我:

noClasses().should().callCodeUnitWhere(
    JavaCall.Predicates.target(
        AccessTarget.Predicates.constructor()
        .and(AccessTarget.Predicates.declaredIn(JavaClass.Predicates.assignableTo(Throwable.class)))
        .and(DescribedPredicate.not(AccessTarget.Predicates.declaredIn(JavaClass.Predicates.assignableTo(BaseException.class))))
    )
);

如果您BaseException位于分析范围内,则需要排除该类:noClasses().that(not(belongToAnyOf(BaseException.class)))


推荐阅读