我的团队在将对象序列化为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。此外,我们的团队也不能更改构建脚本,它在公司范围内受到控制和标准化。
答案 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());
}
}