如何验证@ Xml.propOrder注释值?

时间:2018-06-18 09:47:34

标签: java xml annotations

我的团队在将对象序列化为XML时遇到了一个反复出现的问题:类属性会更新,但@Xml.propOrder注释值不会(人们忘记),这会导致以下错误:

  

属性baz出现在@ XmlType.propOrder中,但不存在这样的属性。

如何自动执行单元测试以检查在注释值中声明@Xml.propOrder未声明字段或拼写错误的所有类?

E.g:

@XmlRootElement
@XmlType(name = "FooBar", propOrder = { "bar", "baz", "foo" })
public class FooBar {

    private String foo;
    private int bar;

    // getters and setters here...
}

IntelliJ有时可以在linting期间发现错误,但是一些团队成员使用Eclipse,因此代码会被调用,maven不会发出任何警告,并且错误的代码会用于测试/ QA。此外,我们的团队也不能更改构建脚本,它在公司范围内受到控制和标准化。

1 个答案:

答案 0 :(得分:0)

我拼凑了一个测试,该测试使用Guava在包名称下加载有关所有类的信息,加载它们,检查它们是否具有@XmlType批注,如果是,则将propOrder元素的值与获得的类属性进行比较通过反思。

我并不完全满意,我想使用Java用来验证注释的相同机制。但是,它有效。

package com.mycompany.datamodel;

import com.google.common.reflect.ClassPath;
import com.google.common.reflect.ClassPath.ClassInfo;
import org.apache.commons.lang.StringUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;

import javax.xml.bind.annotation.XmlType;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.*;

import static org.junit.Assert.assertTrue;

@RunWith(Parameterized.class)
public class PropOrderTest {

    @Parameter
    public Class clazz;

    @Parameters(name = "Test @XmlType.propOrder: {0}")
    public static Collection<Class> data() throws IOException {
        ClassPath classPath = ClassPath.from(Thread.currentThread().getContextClassLoader());
        String packageName = PropOrderTest.class.getPackage().getName();
        Set<ClassInfo> allClasses = classPath.getTopLevelClassesRecursive(packageName);
        List<Class> annotatedClasses = new ArrayList<Class>();
        for (ClassInfo info : allClasses) {
            Class clazz = info.load();
            if (clazz.isAnnotationPresent(XmlType.class)) {
                annotatedClasses.add(clazz);
            }
        }
        return annotatedClasses;
    }

    @Test
    public void testPropOder() throws IOException {
        XmlType xmlType = (XmlType) clazz.getAnnotation(XmlType.class);
        Set<String> propOrder = new HashSet<String>(Arrays.asList(xmlType.propOrder()));
        // remove empty string returned when propOrder is not declared
        propOrder.remove("");
        List<String> fieldNames = getFieldNames();
        propOrder.removeAll(fieldNames);

        assertTrue(formatMessage(propOrder), propOrder.isEmpty());

    }

    private List<String> getFieldNames() {
        Field[] fields = clazz.getDeclaredFields();
        List<String> names = new ArrayList<String>(fields.length);
        for (Field field : fields) {
            names.add(field.getName());
        }
        return names;
    }

    private String formatMessage(Collection<String> propOrder) {
        String message = null;
        String props = "'" + StringUtils.join(propOrder.toArray(), "', '") + "'";
        if (propOrder.size() > 1) {
            message = "Properties %s appear in @XmlType.propOrder, but no such properties exist in class %s (%s.java:1).";
        } else {
            message = "Property %s appears in @XmlType.propOrder, but no such property exists in class %s (%s.java:1).";
        }
        return String.format(message, props, clazz.getName(), clazz.getSimpleName());
    }
}