I’m using MapStruct framework on my java Gradle project, and it works perfectly but I just want to test :
- MapStruct generated sources (converter)
- service class (calls MapStruct’s converter)
I have tried to use another topic to do this but it is not working for me.
This is my MapStruct interface :
@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE) public interface RisqueBOConvertisseur extends BOConvertisseur<RisqueARS, RisqueBO> { @Override RisqueBO convertirDaoVersBo(RisqueARS dao); @Override RisqueARS convertirBoVersDao(RisqueBO bo); }
This is my service class :
@Service public class ServiceRisqueImpl implements ServiceCRUD<RisqueBO> { @Autowired private RisqueRepository risqueRepo; private RisqueBOConvertisseur risqueConv = Mappers.getMapper(RisqueBOConvertisseur.class); private final String nomObjet = "RisqueARS"; public void setRisqueConv(RisqueBOConvertisseur risqueConv) { this.risqueConv = risqueConv; } @Autowired private DossierInternetResource dossierInternet; @Override public RisqueBO recupererParId(String id) { // Récupère le bloc de la base de données final RisqueARS risqueDAO = risqueRepo.findOne(id); // Si aucun résultat -> on déclenche une exception if (null == risqueDAO) { // Déclenche une exception throw new ObjectNotFoundException(construireMessageErreur(this.nomObjet, "L'objet risque correspondant à l'id %s, n'existe pas.", id)); } return risqueConv.convertirDaoVersBo(risqueDAO); } }
When I’m trying to test my service :
@RunWith(MockitoJUnitRunner.class) @SpringBootTest(classes = {ServiceRisqueImpl.class, RisqueBOConvertisseurImpl.class, RisqueBOConvertisseur.class}) public class ServiceRisqueImplTest { @Mock private RisqueRepository risqueRepo; @InjectMocks ServiceRisqueImpl serviceRisque; @Mock private DossierInternetResource dossierInternet; @Mock private RisqueBOConvertisseur risqueConv; @Before public void initMocks() { MockitoAnnotations.initMocks(this); serviceRisque.setRisqueConv(risqueConv); } @Test(expected = ObjectNotFoundException.class) public void testRecupererParIdQuandIdInconnu() { // INITIALISATION // Mock la méthode DAO de retour des données en base when(risqueRepo.findOne(anyString())).thenReturn(null); // PROCESSUS serviceRisque.recupererParId("5"); }
Junit returns:
However the constructor or the initialization block threw an exception : java.lang.ClassNotFoundException: Cannot find implementation for ***.convertisseur.RisqueBOConvertisseur
I have the same error with my converter test :
@RunWith(SpringRunner.class) @SpringBootTest(classes = {RisqueBOConvertisseur.class, RisqueBOConvertisseurImpl.class}) public class RisqueBOConvertisseurTest { @Autowired private RisqueBOConvertisseur configurationMapper; private final RisqueBOConvertisseur risqueConv = Mappers.getMapper(RisqueBOConvertisseur.class); @Test public void test() { // INITIALISATION final RisqueBO risqueBO = new RisqueBO("950095f7-62e7-42e5-a5ae-0d7292e7ad00", "D1", ProfilEpargnant.PROFIL_EPARGNANT_SECURISE, ComportementFaceRisques.REACTION_BAISSE_MARCHE_PANIQUE); // PROCESSUS // final RisqueARS risqueARS = // RisqueBOConvertisseur.INSTANCE.convertirBoVersDao(risqueBO); final RisqueARS risqueARS = configurationMapper.convertirBoVersDao(risqueBO); // VERIFICATIONS assertEquals(risqueBO.getIdRisque(), risqueARS.getIdRisque()); assertEquals(risqueBO.getIdDossierInternet(), risqueARS.getIdDossierInternet()); assertEquals(risqueBO.getCodeComportementRisque(), risqueARS.getCodeComportementRisque()); assertEquals(risqueBO.getCodeProfilEpargnant(), risqueARS.getCodeProfilEpargnant()); } }
How can I test my generated sources converter with MapStruct ?
Advertisement
Answer
My strategy would be to
- mock the mapper as well in your business logic and test it as a separate component. MapStruct can generate spring annotations. Just use
@Mapper( componentModel = "spring" )
to let your DI framework inject the mapper.
Your class would look like:
@Service public class ServiceRisqueImpl implements ServiceCRUD { @Autowired private RisqueRepository risqueRepo; @Autowired private RisqueBOConvertisseur risqueConv; //...
and your test for ServiceRisqueImpl
@Mock private RisqueRepository risqueRepo; @Mock private DossierInternetResource dossierInternet; @Mock private RisqueBOConvertisseur risqueConv; @InjectMocks ServiceRisqueImpl serviceRisque;
You’ll need to mock the mapper as well now, but in doing so, you have far more fine-grained control over your business logic that calls the mapper and uses its result. After all, you can verify the call and mock the result however you like.
And you need to add a separate test for your mapper and test the mapping logic. I usually to roundtrip mapping so:
in -> map -> reverseMap -> out
and use assertj property assertion to see ifin
is the same asout
.