如何修改ArchUnit测试以检测log.error是否包含Throwable参数?
问题分析与解决方案
问题根源
你的测试代码错误地检查了方法的形参类型,而当使用log.error("xxx", param1, e)这种多参数写法时,实际调用的是Log4j2的error(String format, Object... params)可变参数重载。该方法的形参列表是[String, Object[]],自然无法匹配Throwable类型,导致测试误判合规代码为违规。
修改后的测试代码
void errors_should_be_logged_with_context() { ArchRule rule = noClasses() .should(callMethodWhere( target(name("error")).and(target(owner(assignableTo(Logger.class)))) .and(arguments(new DescribedPredicate<>("error logs missing Throwable as last argument") { @Override public boolean test(List<JavaLiteral> arguments) { // 禁止两种违规情况:参数数量≤1,或最后一个参数不是Throwable if (arguments.size() <= 1) { return true; } JavaLiteral lastArgument = arguments.get(arguments.size() - 1); return !lastArgument.getType().isAssignableTo(Throwable.class); } })) ).as("All error logs must include a Throwable as the last argument"); rule.check(ALL_CLASSES); }
关键调整说明
- 替换
rawParameterTypes()为arguments():直接获取日志调用时的实参列表,而非方法定义的形参; - 优化判定逻辑:仅当以下任意一种情况成立时,判定为违规:
log.error调用的参数数量≤1(仅传了日志消息,无上下文或异常);- 调用的最后一个实参不是
Throwable类型;
- 覆盖所有合规场景:无论是直接调用带
Throwable形参的重载(如log.error("msg", e)),还是通过可变参数传递异常(如log.error("msg: {}", param, e)),都会被识别为合规调用。
内容的提问来源于stack exchange,提问作者Uros K
相关产品推荐
相关产品推荐

