Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Provides patterns for unit testing mappers, converters, and bean mappings. Validates entity-to-DTO and model transformation logic in isolation. Generates executable mapping tests with MapStruct and custom converter test coverage. Use when writing mapping tests, converter tests, entity mapping tests, or ensuring correct data transformation between DTOs and domain objects.
.claude/skills/giuseppe-trisciuoglio-unit-test-mapper-converter/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 9% | 0% |
| case-14 | ✓→✓ | = Same ✓ | 28% | 0% |
| case-02 | ✓→✓ | = Same ✓ | 33% | 0% |
| case-03 | ✓→✓ | = Same ✓ | 49% | 0% |
| case-04 | ✓→✓ | = Same ✓ | 5% | 0% |
Provides patterns for unit testing MapStruct mappers and custom converter classes. Covers field mapping accuracy, null handling, type conversions, nested object transformations, bidirectional mapping, enum mapping, and partial updates.
Before testing, verify generated mapper classes exist:
bash# Maven ls target/generated-sources/ # Gradle ls build/generated/sources/
If generated classes are missing:
mvn compile (Maven) or ./gradlew compileJava (Gradle)@Mapper interfaces are in a compiled source setjavaassertThat(mapper.toDto(null)).isNull();
Configure nullValueMappingStrategy in mapper if null should return empty/default.
If null tests fail:
nullValueMappingStrategy = NullValueMappingStrategy.RETURN_NULL to @MappernullValuePropertyMappingStrategy for nested property handlingjavaUser restored = mapper.toEntity(mapper.toDto(original)); assertThat(restored).usingRecursiveComparison().isEqualTo(original);
If bidirectional tests fail:
@Mapping annotations for field name mismatchesunmappedTargetPolicy = ReportingPolicy.ERROR to catch missing mappingsjavaassertThat(dto.getNested()).usingRecursiveComparison().isEqualTo(expected);
If nested tests fail:
uses = NestedMapper.classelementMappingStrategyCustom expressions in @Mapping(target = "field", expression = "java(...)") are not compile-time validated.
If expression tests fail:
Use @ValueMapping for enum-to-enum translations. Test all enum values exhaustively.
Mappers.getMapper() for standalone tests, Spring injection for integration testsusingRecursiveComparison() for complex nested structuresnullValueMappingStrategy and nullValuePropertyMappingStrategy appropriately@Mapping are not validated at compile time—test them explicitlyComplete executable test with imports:
javapackage com.example.mapper; import org.junit.jupiter.api.Test; import org.mapstruct.factory.Mappers; import static org.assertj.core.api.Assertions.*; class UserMapperCompleteTest { private final UserMapper mapper = Mappers.getMapper(UserMapper.class); @Test void shouldMapUserToDto() { User user = new User(1L, "Alice", "alice@example.com", 25); UserDto dto = mapper.toDto(user); assertThat(dto) .isNotNull() .extracting(UserDto::getName, UserDto::getEmail) .containsExactly("Alice", "alice@example.com"); } @Test void shouldMaintainRoundTrip() { User original = new User(1L, "Alice", "alice@example.com", 25); assertThat(mapper.toEntity(mapper.toDto(original))) .usingRecursiveComparison() .isEqualTo(original); } @Test void shouldHandleNullInput() { assertThat(mapper.toDto(null)).isNull(); } }
Additional examples in: references/examples.md
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-14 | pass→pass | 12,057 | 9,805 | -19% | 1 | 1 | 0% | 2,169 | 2,781 | +28% | 0 | 0 | — |
case-01 | fail→pass | 18,167 | 13,111 | -28% | 1 | 1 | 0% | 3,370 | 3,660 | +9% | 0 | 0 | — |
case-02 | pass→pass | 10,058 | 7,437 | -26% | 1 | 1 | 0% | 1,972 | 2,632 | +33% | 0 | 0 | — |
case-03 | pass→pass | 7,747 | 5,796 | -25% | 1 | 1 | 0% | 1,441 | 2,141 | +49% | 0 | 0 | — |
case-04 | pass→pass | 11,238 | 5,617 | -50% | 1 | 1 | 0% | 1,885 | 1,982 | +5% | 0 | 0 | — |
case-15 | pass→pass | 14,311 | 38,276 | +167% | 1 | 1 | 0% | 2,393 | 2,810 | +17% | 0 | 0 | — |
case-05 | pass→pass | 14,067 | 7,605 | -46% | 1 | 1 | 0% | 2,659 | 2,425 | -9% | 0 | 0 | — |
case-06 | pass→pass | 18,462 | 8,632 | -53% | 1 | 1 | 0% | 3,176 | 2,543 | -20% | 0 | 0 | — |
case-07 | pass→pass | 12,328 | 7,353 | -40% | 1 | 1 | 0% | 2,333 | 2,491 | +7% | 0 | 0 | — |
case-08 | pass→pass | 12,494 | 7,436 | -40% | 1 | 1 | 0% | 1,983 | 2,340 | +18% | 0 | 0 | — |
case-09 | pass→pass | 14,647 | 6,442 | -56% | 1 | 1 | 0% | 2,297 | 2,175 | -5% | 0 | 0 | — |
case-16 | pass→pass | 12,186 | 7,670 | -37% | 1 | 1 | 0% | 2,137 | 2,284 | +7% | 0 | 0 | — |
case-10 | pass→pass | 7,429 | 2,804 | -62% | 1 | 1 | 0% | 1,274 | 1,468 | +15% | 0 | 0 | — |
case-11 | pass→pass | 8,408 | 3,097 | -63% | 1 | 1 | 0% | 1,411 | 1,557 | +10% | 0 | 0 | — |
case-12 | pass→pass | 8,903 | 3,150 | -65% | 1 | 1 | 0% | 1,350 | 1,515 | +12% | 0 | 0 | — |
case-13 | pass→pass | 4,685 | 5,270 | +12% | 1 | 1 | 0% | 874 | 1,920 | +120% | 0 | 0 | — |
case-17 | pass→pass | 13,077 | 10,727 | -18% | 1 | 1 | 0% | 2,105 | 2,721 | +29% | 0 | 0 | — |
case-18 | pass→pass | 9,490 | 6,721 | -29% | 1 | 1 | 0% | 1,934 | 2,423 | +25% | 0 | 0 | — |
case-19 | pass→pass | 11,289 | 7,799 | -31% | 1 | 1 | 0% | 2,324 | 2,537 | +9% | 0 | 0 | — |
case-20 | pass→pass | 16,475 | 10,517 | -36% | 1 | 1 | 0% | 3,082 | 3,258 | +6% | 0 | 0 | — |
case-21 | pass→pass | 10,345 | 7,223 | -30% | 1 | 1 | 0% | 1,986 | 2,407 | +21% | 0 | 0 | — |
case-22 | pass→pass | 13,474 | 9,084 | -33% | 1 | 1 | 0% | 2,355 | 2,628 | +12% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +5 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.