Reputation: 1842
I have a Java POJO.
public class Emp {
private String name;
private int id;
}
I have a list of employees (target):
List<Emp> target = new ArrayList<Emap>();
// Add emp object in list
assertThat(target, containsInAnyOrder(????));
In containsInAnyOrder, I have to use something like i.e. hasProperty("name" , is(equalTo("John")). I have to check for a specific property in the list for specific value so what should be the syntax. I did not find any example of "containsInAnyOrder" with List of objects.
Upvotes: 3
Views: 2050
Reputation: 140417
I understand that you want a "generic" thing like: iterate a whole list; then retrieve a field of an object via name; to then check if any of the elements has a matching thing.
I think there is no such thing in Hamcrest: as that is ay too complicated for a pre-defined matcher.
In that sense, the only "answer" to exactly this requirement would be to create your own customer matcher that uses reflection to actually do that.
More details: you can start with an older answer of mine that contains a ready to use matcher that works for lists.
Actually, the only thing left to do now: change my list matcher to perform a different kind of check. And there you could make use of the Apache Commons EqualsBuilder listed in the other answer.
There should be no big hurdle in implementing that; its just "work".
But: I am not sure if that is really the correct approach. As said; the question you are trying to solve there sounds very specific too me; and you know: any unit test that uses reflection lacks the same problem that any "reflection based" code has - the compiler will not tell you, when somebody changes your production code; for example by changing the name of the field name
.
Thus: instead of using reflection, I would rather compromise on the "production code" side of things; for example by adding a simple getter:
public class Emp {
... fields
String getName() { return name; }
And instead of using reflection to compare generic properties, you write a matcher that knows to use that getter to fetch names and compare them.h
Upvotes: 1
Reputation: 3543
If your object-to-compare is always as simple as a Java Pojo, then maybe you can take a look of EqualsBuilder from Apache Commons Lang3. In particular, this method:
public static boolean reflectionEquals(Object lhs, Object rhs, boolean testTransients)
You can implement your own "equals" matcher which delegates the comparison to reflectionEquals
.
To do that, you subclass the TypeSafeDiagnosingMatcher<T>
class from Hamcrest.
class ReflectiveEqualsMatcher<T> extends TypeSafeDiagnosingMatcher<T> {
private final T other;
public ReflectiveEqualsMatcher(T divisor) {
this.other = divisor;
}
@Override
protected boolean matchesSafely(T me, Description description) {
return EqualsBuilder.reflectionEquals(me, other, true);
}
@Override
public void describeTo(Description description) {
}
public static <T> ReflectiveEqualsMatcher<T> same(T other) {
return new ReflectiveEqualsMatcher(other);
}
}
To use it:
//static import ReflectiveEqualsMatcher.same first
assertThat(target, containsInAnyOrder(same(obj1), same(obj2), same(obj3)));
Upvotes: 1