How do I create an ArchUnit rule to verify all exceptions thrown inherit from a specific custom exception?

huangapple go评论89阅读模式
英文:

How do I create an ArchUnit rule to verify all exceptions thrown inherit from a specific custom exception?

问题

以下是您提供的代码部分的翻译:

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

我在使用ArchUnit编写这个规则时遇到了困难我目前的代码如下所示

private static final ArchCondition 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 THROWS_NON_CUSTOM_EXCEPTION =
callCodeUnitWhere(
target(is(constructor()))
.and(
originOwner(
is(assignableTo(Throwable.class))
)
)
);


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

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

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


这返回了每个构造函数,甚至是那些可分配给CustomException的异常的构造函数。

在ArchUnit中,编写一个规则以返回调用所有者可分配给Throwable的构造函数的每个代码单元,同时*不*可分配给CustomException的方法是什么?
英文:

One of my architecture rules is that all exceptions thrown by the application code must be either CustomException, or a subclass of CustomException.

I am having difficulty writing this rule in ArchUnit. What I have currently is the following:

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);

Running this rule returns true (the JUnit test passes) even though I have code that throws an exception that is not also a CustomException.

I have tested the part of the rule that detects that the constructor has an owner that is assignable to Throwable:

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

This correctly returns every place in the code that creates any Throwable.

The problem seems to be in my code that attempts to find owners that are NOT assignable to CustomException:

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

This returns every constructor, even those for exceptions that are assignable to CustomException.

What is the proper way in ArchUnit to write a rule that returns every code unit that calls a constructor whose owner is assignable to Throwable, and not assignable to CustomException?

答案1

得分: 2

我认为你只需要将你已经拥有的部分组合起来。以下的代码对我有效:

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)))

英文:

I think you just need to combine the pieces that you already have. The following code works for me:

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))))
	)
);

If your BaseException resides in the analyzed scope you will need to exclude that class: noClasses().that(not(belongToAnyOf(BaseException.class))).

huangapple
  • 本文由 发表于 2020年8月20日 21:52:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/63506602.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定