Reputation: 1108
I have quite complex object structure (with bunch of primitive fields and object references) and want to test all fields except -a few- of them. As an example;
ComplexObject actual = generateMagically("someInput");
ComplexObject expected = ActualFunction.instance.workMagically(actual);
// we want to be sure that workMagically() would create a new ComplexObject
// with some fields are different than "actual" object.
// assertThat(actual, samePropertyValuesAs(expected)); would check all fields.
// what I want is actually; - notice that "fieldName1" and "fieldName2" are
// primitives belong to ComplexObject
assertThat(actual, samePropertyValuesExceptAs(expected, "fieldName1", "fieldName2"))
Since I don't want to check all fields manually, I believe there must be a way to write that test elegantly. Any ideas?
Cheers.
Upvotes: 11
Views: 14383
Reputation: 764
Just pass the list of properties to ignore as 2nd parameter to samePropertyValuesAs.
Hamcrest matcher API
public static <B> Matcher<B> samePropertyValuesAs(B expectedBean, String... ignoredProperties)
e.g.
samePropertyValuesAs(salesRecord,"id")
Upvotes: 6
Reputation: 4056
You should have a look at shazamcrest, a great Hamcrest
extension that offers what you need.
assertThat(expected, sameBeanAs(expectedPerson).ignoring("fieldName1").ignoring("fieldName2"));
See https://github.com/shazam/shazamcrest#ignoring-fields
Upvotes: 11
Reputation: 20875
Last time I had a similar requirements I came to the conclusion that manually writing both code and tests to assert that some values are updated is inherently fagile and error-prone.
I externalized the fields in a bag object and generated the Java source files for both the bag class itself and the copier at compile time. This way you can test actual code (the generator) and have the actual definition of the domain in exactly one place, so the copy code can't be out-of-date.
The language to describe the property can be anything you are comfortable with, from JSON-schema to XML to Java itself (Java example follows - custom annotations are to be consumed from the generator)
public class MyBag {
@Prop public int oh;
@Prop public String yeah;
}
Upvotes: 0
Reputation: 13546
In general I see two solutions if ComplexObject
can be modified by yourself.
You could introduce an interface that represents the properties of ComplexObject
that are being changed by ActualFunction
. Then you can test that all properties of that new interface have changed. This would require that ComplexObject
implements that new interface.
Another approach would be to replace the properties of ComplextObject
that are changed by ActualFunction
with a new property of a new type that contains all those properties. A better design would then be to let ActualFunction
return an instance of the new type.
Upvotes: 0