2

I have started trying to get my Unit Tests as cleaner as possible and I came across with: How could I compare in a clean way a DTO and a Domain Model (DM) which contain more than 10 attributes and share some of them but not all?

Detail: There can be shared attributes but with different type or different name so reflection cannot be used in this case.

Example:

class Person {
     private String id;
     private String name;
     private String lastName;
     private Date   dateOfbirth;
}

class PersonDto{
     private String id;
     private String name;
     private String lastName;
     private int    dateOfBirth;
}

The DTO should not hold any kind of complex logic as it is only to transfer Data between Client - Controller - Service.

The DM to persist and provide information between Service - Repository layers. But it should not have any kind of complex logic (equals and hashcode so far).

Then I was thinking... Should I create a TestHelperComparator to perform this operation? or implement in the DTO or DM a method to Compare to each other? or what is the best practice in this case?

Karol Dowbecki
  • 43,645
  • 9
  • 78
  • 111
dbenor
  • 55
  • 1
  • 8
  • The DTO and the domain objects shouldn't know each other, or it would introduce weird dependencies. – Arnaud Mar 05 '19 at 16:12
  • Possible duplicate of [how to generically compare entire java beans?](https://stackoverflow.com/questions/472626/how-to-generically-compare-entire-java-beans) – stevecross Mar 05 '19 at 16:16
  • I know, that's why I was thinking it is not a good idea to have a method inside of them to compare them and the way to create a DTO and DM is always by Mappers. And no @stevecross is not duplicated, I cannot use reflection basically because some of the attributes have different type or name. Reflection can be used only when they are exactly the same name and type. Also when you are using any kind of library as ModelMapper or other. – dbenor Mar 05 '19 at 16:16

1 Answers1

2

You probably have the DTO to domain mapping logic somewhere in your code e.g. PersonToDtoMapper class. Make sure the mapping logic is encapsulated in a separate class. You can then reuse this mapper class in your unit tests, translating from one format to another when you have to compare.

As long as PersonToDtoMapper is tested in it's own test there reusing it in other tests shouldn't be a problem, the errors will be easy to spot if PersonToDtoMapperTest fails.

Karol Dowbecki
  • 43,645
  • 9
  • 78
  • 111
  • Thank you for the answer. The case is, I have my mapper but what I want is in my test, I want to check that the DM sent is similar to the DTO received. – dbenor Mar 05 '19 at 16:15
  • If the assertion is repeated across many test classes than it makes sense to extract it into a class. If it's only a single test class than the logic can be kept in a single util method. It's important to not to repeat yourself in the test but it's more important for the tests to be readable. – Karol Dowbecki Mar 05 '19 at 16:17
  • I see... this is actually what I wanted to be sure about, I did not want to mess with classes but at the same time also I did not want to create a util class for this but I can understand is the best approach as I will have to use it in another tests. – dbenor Mar 05 '19 at 16:22
  • If you do not mind @Karol, is there a better way to compare each attribute a part of "if(...)" ? – dbenor Mar 05 '19 at 16:32
  • In tests you should be using assertions instead of simple `if` to compare e.g. [AssertJ](https://joel-costigliola.github.io/assertj/). Your question is very broad, hard to guess what you are referring to. – Karol Dowbecki Mar 05 '19 at 16:34
  • 1
    @dbenor Also check tools like MapStruct that can generate mappers at compile time for you. – chrylis -cautiouslyoptimistic- Mar 05 '19 at 16:36
  • @Karol Why I ask this is, in my TestHelper have a method compareDmWithDto(domain, dto) which returns a boolean and catch that boolean in my assertTrue(TestHelper.compaerDmWithDto(domain,dto)) instead of create an Assert per attribute. – dbenor Mar 05 '19 at 16:37
  • 1
    @chrylis, I was thinking about it, unfortunately this issue is coming from a project in my company, I told them to move to MapStruct actually as I saw was better in performance than the others, but their answer was a clearly No... but thank you anyway – dbenor Mar 05 '19 at 16:38