web-dev-qa-db-fra.com

Comment écrire le test Junit pour le mappeur abstrait mapstruct injecté via Spring

J'utilise MapStruct, mapstruct-jdk8 version 1.1.0.Final et je définis une classe abstraite que j'injecte via Spring.

Je cherche un moyen de les tester via Junit Test? J'ai essentiellement un mappeur principal qui utilisera 2 sous-mappeurs

@Mapper(componentModel = "spring", uses = {SubMapper1.class, SubMapper2.class})
public abstract class MainMapper {

  @Mapping(target = "field1", qualifiedByName = {"MyMapper2Name", "toEntity"})
  public abstract MyEntity toEntity(MyDto pDto);

  public MyDto fromEntity(MyEntity pEntity) {
     // Specific code, hence why I use Abstract class instead of interface. 
  }
}

J'ai essayé plusieurs choses, mais je ne parviens pas à installer correctement le mappeur pour le tester.

@RunWith(SpringRunner.class)
public class MainMapperTest {

    private MainMapper service = Mappers.getMapper(MainMapper.class);

    @Test
    public void testToEntity() throws Exception {
.....

Java.lang.RuntimeException: Java.lang.ClassNotFoundException: impossible de trouver l'implémentation pour com.mappers.MainMapper

J'ai aussi essayé via @InjectMock mais pas de dés non plus.

Impossible d'instancier le champ @InjectMocks nommé 'service'. Vous n'avez pas fourni l'instance à la déclaration du champ, j'ai donc essayé de construire le exemple. Cependant, j'ai échoué parce que: le type 'MainMapper est une classe abstraite.

Et via Spring @Autowired 

Causé par: org.springframework.beans.factory.NoSuchBeanDefinitionException: No Bean qualifiant de type 'com.mappers.MainMapper' disponible: attendu au moins 1 haricot qui se qualifie comme candidat autowire. Dépendance annotations: {@ org.springframework.beans.factory.annotation.Autowired (required = true)}

J'imagine que cela pourrait avoir à voir avec le processeur d'annotation, et le mappeur n'étant pas généré lorsque je lance test . J'ai trouvé cette classe à titre d'exemple .

Cependant, la classe AnnotationProcessorTestRunner ne semble pas être disponible avant la version 1.2, qui n'a pas encore de version finale.

Ma question est donc de savoir comment écrire des tests Junit pour tester mon mappeur de classes abstraites mapstruct que j'utilise via l'injection de ressort dans mon code.

7
TheBakker

Voici comment j'ai déclaré ma classe de test pour la classe abstraite ConfigurationMapper à l'aide de 2 sous-mappeurs en réponse au commentaire de @Richard Lewan

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {ConfigurationMapperImpl.class, SubMapper1Impl.class, SubMapper2Impl.class})
public class ConfigurationMapperTest {

Vous utilisez l'impl généré dans l'annotation SpringBootTest Et vous injectez ensuite la classe que vous voulez tester.

@Autowired
private ConfigurationMapper configurationMapper;

Faites-moi savoir si vous avez besoin de plus d'informations, mais à partir de là, rien de plus simple… Je ne me moquais pas du subMapper, car il était préférable pour moi de tester tout le processus de mappage à la fois.

7
TheBakker

Vous rencontrez plusieurs problèmes:

  1. Vous devez utiliser Mappers#getMapper(Class) uniquement avec la valeur par défaut componentModel, sinon le mappeur ne sera pas instancié correctement. Si vous obtenez la RuntimeException, cela signifie que la classe d'implémentation n'a pas été générée. Assurez-vous que vous avez une configuration correcte
  2. Vous devez tester contre la mise en oeuvre MainMapperImpl et non contre la classe abstraite.
  3. Si vous voulez tester avec le bean spring, vous devez utiliser la variable ComponentScan correcte et vous assurer que l'implémentation et les mappeurs utilisés peuvent être câblés automatiquement.

La classe que vous avez liée est une classe de test incorrecte et n'est pas liée à votre scénario de test. Jetez un coup d’œil à this cas de test d’intégration pour l’intégration printanière.

La AnnotationProcessorTestRunner fait partie de nos tests et est utilisée pour tester le processeur d'annotation. Elle existe depuis le début. Cela ne fait pas partie des communiqués.

1
Filip