0

I want to create unit test that handle an exception when dto fields != entity fields. And print missing and extra fields. Is it possible to make it with MapStruct?

Simple example without annotations and boilerplate code. I have

public class TestDto {
  long id;
  String name;
  int age;
  long customerId;
  String phone;
}

And Entity

public class TestEntity {
  long id;
  String name;
  int age;
  Customer customer;
  String address;
}

@Mapping(source = "person.id", target = "personId") // in my Mapper class
TestDto toDto(Test entity);

output: Missing fields for dto. Please add!: address; Extra fields for dto. Please remove! : phone;

I tried to use reflection and it didn't work. https://stackoverflow.com/questions/75082277/how-to-find-all-missing-and-extra-fields-in-dto-by-their-entity-using-reflec?noredirect=1#comment132500771_75082277

I'd love to hear any ideas on how to do this.

Taras
  • 106
  • 6
  • 1
    If you want tests to fail if you're missing mappings or have extra fields, you can instruct MapStruct to fail at compile time if that occurs. You can do so by setting both `unmappedSourcePolicy` and `unmappedTargetPolicy` of the `@Mapper` annotation to `ERROR`. I advise to also set `typeConversionPolicy` to `ERROR`. It's not exactly what you asked for, but I myself prefer errors sooner (compile time) than later (test time). – Rob Spoor Jan 11 '23 at 17:12
  • @RobSpoor Thanks for the good advice. But my task is to write a test, and not change the logic of the production version of the application. – Taras Jan 11 '23 at 17:16
  • Apache commons is full of library to introspect classes (and superclass) and extract properties with any modifier. Just extract all properties from source/dest dto, separate missing properties from source/dest and for every commons properties which is a dto (or a target type), apply the same process recursively. `MapStruct` is used to map dto, not to describe structure differences – Luca Basso Ricci Jan 12 '23 at 06:47

1 Answers1

0

Mapstruct itself cannot do this, because it runs compile time. However you can use the generated code to check this if you have completely filled objects.

Simply map a completely filled dto to an entity, and then back to the dto object. Now compare the resulting dto with your original dto and you can figure out which fields are not the same anymore.

Repeat this for a completely filled entity by mapping it to a dto and back to entity and you've got the entity class covered.

In code it looks something like this:

@Test
void dtoFieldTest() {
    TestDto original = createFilledTestDto();
    TestMapper testMapper = TestMapper.INSTANCE;
    
    TestDto result = testMapper.mapEntityToDto(testMapper.mapDtoToEntity(original));

    // assertj assertions
    assertThat(result).isEqualTo(original);
    // or if you cannot use the dto equals method.
    assertThat(result).usingRecursiveComparison().isEqualTo(original);
}
Ben Zegveld
  • 1,186
  • 2
  • 6