title: how to test MapStruct mapper implementation and mock its dependencies
body: <p>I am using MapStruct to map objects from and to DTOs. My mappers are dependent on some services/repositories to get data from database when for example mapping from DTo that has list of IDs to POJO that has a list of other POJOs.
  For this I have a Mapper inteface and an abstract class Decorator implementing this interface. 
  I want to test the mapper but I need to mock the services inside the decorator. My question is how can I achieve this?</p>
  
  <p>Now I know there would be better if mapper didn't have so much dependencies (SOLID), but I need to finish the project fast now.</p>
  
  <p>It looks like this:</p>
  
  <p>Mapper</p>
  
  <pre><code>@Mapper(componentModel = "spring", injectionStrategy = InjectionStrategy.CONSTRUCTOR)
  @DecoratedWith(AuthorMapperDecorator.class)
  public interface AuthorMapper {
  
      AuthorDTO map(Author entity);
  
      @Mapping(target = "songs", ignore = true)
      Author map(AuthorDTO dto);
  
      @Mapping(target = "coauthorSongs", ignore = true)
      @Mapping(target = "songs", ignore = true)
      @Mapping(target = "id", ignore = true)
      @Mapping(target = "name", source = "name")
      Author map(UniversalCreateDTO dto);
  }
  </code></pre>
  
  <p>Decorator</p>
  
  <pre><code>public abstract class AuthorMapperDecorator implements AuthorMapper {
  
    @Autowired
    @Qualifier("delegate")
    private AuthorMapper delegate;
    @Autowired
    private SongCoauthorService songCoauthorService;
    @Autowired
    private SongService songService;
  
    @Override
    public Author map(AuthorDTO dto) {
      var author = delegate.map(dto);
      author.setBiographyUrl(null);
      author.setPhotoResource(null);
      author.setCoauthorSongs(new HashSet&lt;&gt;(songCoauthorService.findByAuthorId(dto.getId())));
      author.setSongs(new HashSet&lt;&gt;(songService.findByAuthorId(dto.getId())));
      return author;
    }
  
    @Override
    public Author map(UniversalCreateDTO dto) {
      var author = delegate.map(dto);
      author.setSongs(new HashSet&lt;&gt;());
      author.setCoauthorSongs(new HashSet&lt;&gt;());
      author.setId(Constants.DEFAULT_ID);
      return author;
    }
  }
  </code></pre>
  
  <p>Then there are the generated implementations:</p>
  
  <pre><code>@Generated(
      value = "org.mapstruct.ap.MappingProcessor",
      date = "2020-05-13T22:50:36+0200",
      comments = "version: 1.3.1.Final, compiler: javac, environment: Java 13.0.2 (Oracle Corporation)"
  )
  @Component
  @Qualifier("delegate")
  public class AuthorMapperImpl_ implements AuthorMapper {
  
      @Override
      public AuthorDTO map(Author entity) {
          if ( entity == null ) {
              return null;
          }
  
          Builder authorDTO = AuthorDTO.builder();
  
          authorDTO.id( entity.getId() );
          authorDTO.name( entity.getName() );
  
          return authorDTO.build();
      }
  
      @Override
      public Author map(AuthorDTO dto) {
          if ( dto == null ) {
              return null;
          }
  
          Author author = new Author();
  
          author.setId( dto.getId() );
          author.setName( dto.getName() );
  
          return author;
      }
  
      @Override
      public Author map(UniversalCreateDTO dto) {
          if ( dto == null ) {
              return null;
          }
  
          Author author = new Author();
  
          author.setName( dto.getName() );
  
          return author;
      }
  }
  </code></pre>
  
  <pre><code>@Generated(
      value = "org.mapstruct.ap.MappingProcessor",
      date = "2020-05-13T22:50:36+0200",
      comments = "version: 1.3.1.Final, compiler: javac, environment: Java 13.0.2 (Oracle Corporation)"
  )
  @Component
  @Primary
  public class AuthorMapperImpl extends AuthorMapperDecorator implements AuthorMapper {
  
      private final AuthorMapper delegate;
  
      @Autowired
      public AuthorMapperImpl(@Qualifier("delegate") AuthorMapper delegate) {
  
          this.delegate = delegate;
      }
  
      @Override
      public AuthorDTO map(Author entity)  {
          return delegate.map( entity );
      }
  }
  </code></pre>