-
-
Notifications
You must be signed in to change notification settings - Fork 999
Closed
Description
Expected behavior
I have this mapping defined
@Mapping(target = "details.name", source = "details.name")
@Mapping(target = "details.type", constant = "DOG")
Animal map(Dog dog);
@Mapping(target = "details.name", source = "details.name")
@Mapping(target = "details.type", constant = "CAT")
Animal map(Cat cat);
I would expect, that the field details.type is set dependent on the source object.
Actual behavior
I have definied this test
class AnimalMapperTest {
@Test
void mapCat() {
Cat cat = new Cat(new Details("cat"));
Animal animal = AnimalMapper.INSTANCE.map(cat);
assertEquals(AnimalDetails.Type.CAT, animal.getDetails().getType());
assertEquals(cat.getDetails().getName(), animal.getDetails().getName());
}
@Test
void mapDog() {
Dog dog = new Dog(new Details("cat"));
Animal animal = AnimalMapper.INSTANCE.map(dog);
assertEquals(AnimalDetails.Type.DOG, animal.getDetails().getType());
assertEquals(dog.getDetails().getName(), animal.getDetails().getName());
}
}
There, I get this exception:
org.opentest4j.AssertionFailedError:
Expected :CAT
Actual :DOG
<Click to see difference>
This is because mapstruct uses this method
animal.setDetails( detailsToAnimalDetails( dog.getDetails() ) );
protected AnimalDetails detailsToAnimalDetails(Details details) {
if ( details == null ) {
return null;
}
AnimalDetails animalDetails = new AnimalDetails();
animalDetails.setName( details.getName() );
animalDetails.setType( AnimalDetails.Type.DOG );
return animalDetails;
}
And there, it does not distinguish between Dog and Cat.
With the version 1.5.5.Final this mapping did not fail.
Steps to reproduce the problem
import lombok.Data;
@Data
public class Animal {
private AnimalDetails details;
}
import lombok.Data;
@Data
public class AnimalDetails {
private Type type;
private String name;
public enum Type {
CAT,
DOG
}
}
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
@Mapper
public interface AnimalMapper {
AnimalMapper INSTANCE = Mappers.getMapper(AnimalMapper.class);
@Mapping(target = "details.name", source = "details.name")
@Mapping(target = "details.type", constant = "DOG")
Animal map(Dog dog);
@Mapping(target = "details.name", source = "details.name")
@Mapping(target = "details.type", constant = "CAT")
Animal map(Cat cat);
}
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class AnimalMapperTest {
@Test
void mapCat() {
Cat cat = new Cat(new Details("cat"));
Animal animal = AnimalMapper.INSTANCE.map(cat);
assertEquals(AnimalDetails.Type.CAT, animal.getDetails().getType());
assertEquals(cat.getDetails().getName(), animal.getDetails().getName());
}
@Test
void mapDog() {
Dog dog = new Dog(new Details("cat"));
Animal animal = AnimalMapper.INSTANCE.map(dog);
assertEquals(AnimalDetails.Type.DOG, animal.getDetails().getType());
assertEquals(dog.getDetails().getName(), animal.getDetails().getName());
}
}
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class Cat {
Details details;
}
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class Details {
String name;
}
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class Dog {
Details details;
}
MapStruct Version
1.6.0