Given the following class...
public class UserAccount {
private Long id;
private String email;
private String activationCode;
private Date createDate;
}
... I need to compare the actual object with an expected object using AssertJ. However the fields id, activationCode and createDate have dynamic value which I can't hard-code into the assertion.
So the following assertion would fail:
assertThat(actualUserAccount).isEqualTo(expectedUserAccount);
Then I found the following which would ignore certain fields:
assertThat(actualUserAccount)
.usingRecursiveComparison()
.ignoringFields("id", "activationCode", "createDate")
.isEqualTo(expectedUserAccount);
But what I'm actually looking for is to assert for the objects being equal with the following special checks on certain fields:
id with any Long value?activationCode with any String value?createDate with any Date value?Or is there no other way than to write one assertion for each field?
You can specify how to compare certain fields with withEqualsForFields so you could write something like:
assertThat(actualUserAccount)
.usingRecursiveComparison()
.withEqualsForFields((id1, id2) -> id1 instanceof Long && id2 instanceof Long, "id")
.isEqualTo(expectedUserAccount);
I'm checking both ids fields since there is no garantee that id1 is the actual id and id2 the expected id.
You could also write a generic method like BiPredicate<A, B> isType(T type) that returns a bipredicate checking both parameters are of the type T (my suggested signature might not work but you get the idea), that would let you write:
assertThat(actualUserAccount)
.usingRecursiveComparison()
.withEqualsForFields(isType(Long.class), "id")
.withEqualsForFields(isType(String.class), "activationCode")
.withEqualsForFields(isType(Date.class), "createDate")
.isEqualTo(expectedUserAccount);
Here's what isType looks like (I haven't tested it though):
<A, B, T extends Class<?>> BiPredicate<A, B> isType(T type) {
return (a, b) -> type.isInstance(a) && type.isInstance(b);
}
Having said that, I would probably not go that way and write additional assertions.
For reference: https://assertj.github.io/doc/#assertj-core-recursive-comparison-comparators
If you want to verify that all the fields have a value you could use hasNoNullFieldsOrProperties, while returns can be used to refine the verification of email (assuming that getters are exposed):
assertThat(actualUserAccount)
.hasNoNullFieldsOrProperties()
.returns(expectedUserAccount.getEmail(), from(UserAccount::getEmail));
If you must enforce the type of the fields, you can chain:
.extracting(UserAccount::getId, UserAccount::getEmail, UserAccount::getActivationCode, UserAccount::getCreateDate)
.hasExactlyElementsOfTypes(Long.class, String.class, String.class, Date.class);
If getters are not available, your original example is probably the only option to verify the value of email:
assertThat(actualUserAccount)
.usingRecursiveComparison()
.ignoringFields("id", "activationCode", "createDate")
.isEqualTo(expectedUserAccount);
But still you can use extracting(String...) instead of extracting(Function...) to enforce the type of the fields:
assertThat(actualUserAccount)
.extracting("id", "email", "activationCode", "createDate")
.hasExactlyElementsOfTypes(Long.class, String.class, String.class, Date.class);
However, these options are not refactoring-friendly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With