我想编写一个 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);
}
显然,我希望对集合的检查像数组一样是递归的,但现在我想让它适用于简单的情况。
对我来说,从你的问题来看,你如何使用
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);
}