1

I need to compare one PatientDTO dto object with other one PatientModel model object.

Both classes are quite similar:

class PatientDTO {
    private String name;
    private List<AddressDTO> address;

    // Constructors, getters and setters
}

class PatientModel {
    private String id;
    private String nameElement;
    private List<AddressModel> addressElement;

    // Constructors, getters and setters
}

class AddressDTO {
    private String city;
    private String country;
    private List<String> linesElement;

    // Constructors, getters and setters
}

class AddressModel {
    private String city;
    private String countryElement;
    private List<String> linesElement;

    // Constructors, getters and setters
}

Main differences are:

  • Some fields are not present on DTOs: PatientDTO.id doesn't exist.
  • Some field names contains suffixes on Model classes: PatientDTO.name <> PatientModel.nameElement.

Other issue I like to solve, is that:

  • Address related assertion should be shared. I mean, Address-like classes are present on other classes, for exemple, Organization, Practitioner...

I'd like to build an assertion like this:

PatientDTO patientDTO;
PatientModel patientModel;

assertThat(patientDTO).isEqual(patientModel);

Shortly:

  1. Should I build a custom assertion?
  2. Should I have an assertion for Address an other one for Patient containing previous Address assertion? How could I get this?
  3. What aboud Address assertion for Patient, Organization

What I want to avoid is code like this:

assertThat(patientDTO).anySatisfy(p->{
    assertThat(p.getName()).withFailMessage("expected name: "+ p.getAddress().getCity()).isEqualTo(patientModel.getNameElement());
    assertThat(p.getAddress().getCity()).withFailMessage("expected city: "+ p.getAddress().getCity()).isEqualTo(patientModel.getCityElement());
    assertThat(p.getAddress().getCountry()).withFailMessage("expected country: "+ p.getAddress().getCountry()).isEqualTo(patientModel.getCountryElement());
    ...
    }
);

I want to avoid above code since Patient classes are really large. Here I've shorted them for clarity purpouses.

Any ideas?

Jordi
  • 20,868
  • 39
  • 149
  • 333

1 Answers1

1

The field-by-field recursive comparison could help for this purpose:

PatientDTO patientDTO = new PatientDTO(...);
PatientModel patientModel = new PatientModel(...);

assertThat(patientDTO).usingRecursiveComparison()
                      .isEqualTo(patientModel);

Some fields are not present on DTOs: PatientDTO.id doesn't exist.

There are a few methods that can be used to tune the comparison and ignore fields:

Some field names contains suffixes on Model classes: PatientDTO.name <> PatientModel.nameElement.

This is currently not supported and was also asked in https://stackoverflow.com/a/70381488/9714611. We plan to raise a feature request about it and I will update the answer once the issue link is ready.

Address related assertion should be shared. I mean, Address-like classes are present on other classes, for exemple, Organization, Practitioner...

If the target is always isEqualTo, probably a custom assertion implementation is not needed as long as the limitation of the recursive comparison about not being able to compare fields with different names is not a show-stopper. These fields would require ad-hoc comparison until a better solution is available.

If the target is to provide assertions in a domain-specific language, like:

assertThat(patientDTO).hasAddress(addressDTO);

then a custom assertion implementation can be added.

Also, there is an assertions generator with plugins for Maven and Gradle that can be used to generate assertions based on the class attributes.

Stefano Cordio
  • 1,687
  • 10
  • 20