我有不同的值对象,每个对象都有一组不同的字段。如何使用Hamcrest匹配器检查这些?
public class ValueObjectA {
public Integer field1;
public String field2;
public long filed3;
public Object filed4;
}
public class ValueObjectB {
public String field1;
public int field2;
}
这就是我想要做的事情:
resultA = getResultA();
ValueObjectA expectedA = new ValueObjectA();
expectedA.field1 = 4;
resultB = getResultB();
ValueObjectB expectedB = new ValueObjectB();
expectedB.field1 = "foo";
assertThat(resultA, new ValueObjectMatcher(expectedA));
assertThat(resultB, new ValueObjectMatcher(expectedB));
我找到了一个PropertyMatcher但只使用了公共getter。我可以写类似的东西,使用反射来获取公共字段。但是有现成品吗?
答案 0 :(得分:4)
您可以使用我们最近开源的库来执行此操作。它的工作方式类似于PropertyMatcher,但设计用于执行深度对象图。结果是它在公共领域“正常运作”。
github上的答案 1 :(得分:3)
无论如何,我根据PropertyMatcher编写了一些内容,以防有人想要编写单元测试。 com.j256.ormlite:
public class ValueObjectMatcher extends TypeSafeDiagnosingMatcher {
private final Object expectedVo;
private final Set<String> fieldNames;
private final List<FieldMatcher> fieldMatchers;
public ValueObjectMatcher(final Object expectedVo) {
Field[] fieldsToMatch = expectedVo.getClass().getFields();
this.expectedVo = expectedVo;
this.fieldNames = fieldNamesFrom(fieldsToMatch);
this.fieldMatchers = fieldMatchersFor(expectedVo, fieldsToMatch);
}
@Override
protected boolean matchesSafely(final Object item, final Description mismatchDescription) {
return hasAllFields(item, mismatchDescription) && hasMatchingValues(item, mismatchDescription);
}
@Override
public void describeTo(final Description description) {
description.appendText("same field values as " + expectedVo.getClass().getSimpleName())
.appendList(" <", ", ", ">", fieldMatchers);
}
private boolean hasMatchingValues(final Object item, final Description mismatchDescription) {
mismatchDescription.appendText(item + " has <");
int mismatchCount = 0;
for (FieldMatcher fieldMatcher : fieldMatchers) {
if (!fieldMatcher.matches(item)) {
if (mismatchCount != 0) {
mismatchDescription.appendText(", ");
}
fieldMatcher.describeMismatch(item, mismatchDescription);
mismatchCount++;
}
}
mismatchDescription.appendText(">");
return mismatchCount == 0;
}
private boolean hasAllFields(final Object item, final Description mismatchDescription) {
final Field[] fields = item.getClass().getFields();
final Set<String> itemsFieldNames = fieldNamesFrom(fields);
boolean result = true;
for (String fieldName : fieldNames) {
if (!itemsFieldNames.contains(fieldName)) {
result = false;
mismatchDescription.appendText("missing field: " + fieldName);
}
}
return result;
}
private List<FieldMatcher> fieldMatchersFor(final Object expectedVo, final Field[] fields) {
List<FieldMatcher> result = new ArrayList<FieldMatcher>(fields.length);
try {
for (Field field : fields) {
result.add(new FieldMatcher(field, expectedVo));
}
}
catch (NoSuchFieldException e) {
throw new IllegalStateException("Programmer exception, pls replace programmer: " +
"field list doesn't match with the fields of the provided expectedVo", e);
}
catch (IllegalAccessException e) {
throw new IllegalStateException("Programmer exception, pls replace programmer: " +
"field list doesn't match with the fields of the provided expectedVo", e);
}
return result;
}
private Set<String> fieldNamesFrom(final Field[] fieldsToMatch) {
HashSet<String> result = new HashSet<String>();
for (Field field : fieldsToMatch) {
result.add(field.getName());
}
return result;
}
public class FieldMatcher extends DiagnosingMatcher<Object> {
private final Object expectedFieldValue;
private final String fieldName;
private FieldMatcher(Field field, Object expectedVo) throws NoSuchFieldException, IllegalAccessException {
this.fieldName = field.getName();
this.expectedFieldValue = expectedVo.getClass().getField(fieldName).get(expectedVo);
}
@Override
protected boolean matches(final Object item, final Description mismatchDescription) {
try {
final Field fieldItem = item.getClass().getField(fieldName);
final Object fieldObjectItem = fieldItem.get(item);
if (fieldObjectItem == null) {
if (expectedFieldValue != null) {
mismatchDescription.appendText(fieldName + ": " + fieldObjectItem);
}
} else if (!fieldObjectItem.equals(expectedFieldValue)) {
mismatchDescription.appendText(fieldName + ": " + fieldObjectItem);
}
}
catch (IllegalAccessException e) {
mismatchDescription.appendText(fieldName + " is inaccessible");
e.printStackTrace();
}
catch (NoSuchFieldException e) {
mismatchDescription.appendText(fieldName + " doesn't exist");
e.printStackTrace();
}
return false;
}
@Override
public void describeTo(final Description description) {
description.appendText(fieldName + ": " + expectedFieldValue);
}
}
}