
Unit Test Mapper Converter
Add MapStruct mapper and DTO converter unit tests with JUnit and AssertJ so mapping bugs surface before release.
Overview
Unit Test Mapper Converter is an agent skill for the Ship phase that produces MapStruct mapper unit tests using JUnit and AssertJ to validate DTO and entity field mapping.
Install
npx skills add https://github.com/giuseppe-trisciuoglio/developer-kit --skill unit-test-mapper-converterWhat is this skill?
- MapStruct 1.5.5.Final-style mapper tests via Mappers.getMapper for zero Spring context.
- AssertJ extracting/containsExactly patterns for DTO ↔ entity field parity.
- Examples for single object, reverse mapping, and List<UserDto> batch conversions.
- Maven and Gradle dependency snippets for MapStruct, JUnit Jupiter, and AssertJ.
- Regression-friendly tests when renaming entity fields or adding nullable columns.
- Examples reference MapStruct 1.5.5.Final
- JUnit Jupiter and AssertJ test dependency patterns included
Adoption & trust: 1.2k installs on skills.sh; 271 GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
Your API returns DTOs from MapStruct mappers but you have no tests—so a renamed field ships as null without failing compile.
Who is it for?
Indie Spring API authors using MapStruct who want fast mapper regression tests without bootstrapping the whole application.
Skip if: Projects using manual mapping only, or teams that need end-to-end persistence mapping verified solely through @DataJpaTest suites.
When should I use this skill?
Writing or extending unit tests for MapStruct mappers, DTO converters, or entity mapping classes in Java Spring projects.
What do I get? / Deliverables
You get focused mapper test classes that lock field-level parity for toDto, toEntity, and collection mappings before merge or deploy.
- Mapper test classes with entity/DTO fixtures and field-level assertions
- Optional dependency blocks for MapStruct and test libraries
Recommended Skills
Journey fit
Mapper tests are classic Ship-phase regression gates—wrong field mapping breaks APIs silently after refactors. Pure unit tests for mappers belong under testing, not backend implementation docs alone.
How it compares
Template-style unit tests for MapStruct—not a code generator for mappers themselves.
Common Questions / FAQ
Who is unit-test-mapper-converter for?
Solo and small-team Java developers on Spring APIs who rely on MapStruct and need agent-assisted JUnit coverage for converters.
When should I use unit-test-mapper-converter?
During Ship testing when adding or changing DTO mappers, or after refactors to entities where mapping parity must be re-verified.
Is unit-test-mapper-converter safe to install?
It writes test source under your repo; review the Security Audits panel on this Prism page and run builds only in trusted projects.
SKILL.md
READMESKILL.md - Unit Test Mapper Converter
# Mapper & Converter Test Examples ## Setup ### Maven ```xml <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct</artifactId> <version>1.5.5.Final</version> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.assertj</groupId> <artifactId>assertj-core</artifactId> <scope>test</scope> </dependency> ``` ### Gradle ```kotlin dependencies { implementation("org.mapstruct:mapstruct:1.5.5.Final") testImplementation("org.junit.jupiter:junit-jupiter") testImplementation("org.assertj:assertj-core") } ``` ## Basic Pattern: MapStruct Mapper ```java @Mapper(componentModel = "spring") public interface UserMapper { UserDto toDto(User user); User toEntity(UserDto dto); List<UserDto> toDtos(List<User> users); } class UserMapperTest { private final UserMapper userMapper = Mappers.getMapper(UserMapper.class); @Test void shouldMapUserToDto() { User user = new User(1L, "Alice", "alice@example.com", 25); UserDto dto = userMapper.toDto(user); assertThat(dto) .isNotNull() .extracting("id", "name", "email", "age") .containsExactly(1L, "Alice", "alice@example.com", 25); } @Test void shouldMapDtoToEntity() { UserDto dto = new UserDto(1L, "Alice", "alice@example.com", 25); User user = userMapper.toEntity(dto); assertThat(user) .isNotNull() .hasFieldOrPropertyWithValue("id", 1L) .hasFieldOrPropertyWithValue("name", "Alice"); } @Test void shouldMapListOfUsers() { List<User> users = List.of( new User(1L, "Alice", "alice@example.com", 25), new User(2L, "Bob", "bob@example.com", 30) ); List<UserDto> dtos = userMapper.toDtos(users); assertThat(dtos) .hasSize(2) .extracting(UserDto::getName) .containsExactly("Alice", "Bob"); } @Test void shouldHandleNullEntity() { assertThat(userMapper.toDto(null)).isNull(); } } ``` ## Nested Object Mapping ```java class User { private Long id; private String name; private Address address; private List<Phone> phones; } class NestedObjectMapperTest { private final UserMapper userMapper = Mappers.getMapper(UserMapper.class); @Test void shouldMapNestedAddress() { Address address = new Address("123 Main St", "New York", "NY", "10001"); User user = new User(1L, "Alice", address); UserDto dto = userMapper.toDto(user); assertThat(dto.getAddress()) .isNotNull() .hasFieldOrPropertyWithValue("street", "123 Main St"); } @Test void shouldMapListOfNestedPhones() { List<Phone> phones = List.of( new Phone("123-456-7890", "MOBILE"), new Phone("987-654-3210", "HOME") ); User user = new User(1L, "Alice", null, phones); UserDto dto = userMapper.toDto(user); assertThat(dto.getPhones()) .hasSize(2) .extracting(PhoneDto::getNumber) .containsExactly("123-456-7890", "987-654-3210"); } @Test void shouldHandleNullNestedObjects() { User user = new User(1L, "Alice", null); assertThat(userMapper.toDto(user).getAddress()).isNull(); } } ``` ## Custom Mapping Methods ```java @Mapper(componentModel = "spring") public interface ProductMapper { @Mapping(source = "name", target = "productName") @Mapping(source = "price", target = "salePrice") @Mapping(target = "discount", expression = "java(product.getPrice() * 0.1)") ProductDto toDto(Product product); } class CustomMappingTest { private final ProductMapper mapper = Mappers.getMapper(ProductMapper.class); @Test void shouldMapFieldsWithCustomNames() { Product product = new Product(1L, "Laptop", 999.99); ProductDto dto = mapper.toDto(product); assertThat(dto) .hasFieldOrPropertyWithValue("productName", "Laptop") .hasFieldOrPropertyWithValue("salePrice", 999.99); } @Test void shouldCalculateDiscountFromExpression() { Product product = new Product(1L