Skip to content
Advertisement

How to tests and mock mapstruct converter?

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

  1. 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;
  1. 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.

  2. 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 if in is the same as out.

4 People found this is helpful
Advertisement