如何在 ArchUnit 测试中检查泛型参数是否可序列化?

问题描述 投票:0回答:1

我想编写一个 ArchUnit 测试来检查可序列化类中的所有字段是否是静态的、瞬态的或可序列化的。这意味着对于所有非原始类型,我必须检查它们是否实现可序列化(如果这些字段属于非原始类型,则递归地)。

对于集合,我想检查它们的泛型是否可序列化,因为集合的可序列化取决于此。

到目前为止,我的规则是这样制定的:

fields().that().areDeclaredInClassesThat().implement(Serializable.class)
        .should().beStatic().orShould().haveModifier(JavaModifier.TRANSIENT)
        .orShould(new SerializableCondition()).check(classes);

其中

SerializableCondition
实现
ArchCondition
并满足以下条件:

private boolean isSerializable(JavaClass javaClass) {
      if (javaClass.isPrimitive()) {
        return true;
      }

      // Recursively check if array components are serializable
      if (javaClass.isArray()) {
        return isSerializable(javaClass.getComponentType());
      }

      // This check does not work as expected
      if (javaClass.isAssignableTo(Collection.class)) {
        var x = ((ParameterizedType)
            javaClass.reflect().getGenericInterfaces()[0])
            .getActualTypeArguments()[0];

        return x instanceof Serializable;
      }

      return javaClass.isAssignableTo(Serializable.class);
    }

显然,我希望对集合的检查像数组一样是递归的,但现在我想让它适用于简单的情况。

java reflection archunit
1个回答
0
投票

对我来说,从你的问题来看,你如何使用

isSerializable
中的
SerializableCondition
既不明显(可能以某种方式通过对测试的
JavaField
rawType
进行评估?),也不清楚
// This check does not work as expected
意味着什么完全正确,但我会尝试这样的事情:

ArchRule rule = fields()
    .that().areDeclaredInClassesThat().implement(Serializable.class)
    .should().beStatic()
    .orShould().haveModifier(JavaModifier.TRANSIENT)
    .orShould(ArchConditions.be(DescribedPredicate.describe("serializable",
        field -> isSerializable(field.getType())
    )));

static boolean isSerializable(JavaType type) {
    JavaClass rawType = type.toErasure();
    return rawType.isPrimitive()
        || rawType.isArray()
            && isSerializable(rawType.getComponentType())
        || rawType.isAssignableTo(Collection.class)
            && type instanceof JavaParameterizedType
            && isSerializable(((JavaParameterizedType) type).getActualTypeArguments().get(0))
        || rawType.isAssignableTo(Serializable.class);
}
© www.soinside.com 2019 - 2024. All rights reserved.