如何测试MapStruct映射器实现并模拟其依赖项

时间:2020-05-16 12:14:32

标签: java spring spring-boot mockito mapstruct

我正在使用MapStruct在DTO之间映射对象。例如,从具有ID列表的DTo映射到具有其他POJO列表的POJO时,我的映射器依赖于某些服务/存储库从数据库获取数据。 为此,我有一个Mapper接口和一个实现此接口的抽象类Decorator。 我想测试映射器,但是我需要模拟装饰器中的服务。我的问题是我该如何实现?

现在我知道,如果mapper没有那么多的依赖关系(SOLID),那会更好,但是我现在需要快速完成该项目。

它看起来像这样:

映射器

@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);
}

装饰器

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<>(songCoauthorService.findByAuthorId(dto.getId())));
    author.setSongs(new HashSet<>(songService.findByAuthorId(dto.getId())));
    return author;
  }

  @Override
  public Author map(UniversalCreateDTO dto) {
    var author = delegate.map(dto);
    author.setSongs(new HashSet<>());
    author.setCoauthorSongs(new HashSet<>());
    author.setId(Constants.DEFAULT_ID);
    return author;
  }
}

然后有生成的实现:

@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;
    }
}
@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 );
    }
}

1 个答案:

答案 0 :(得分:2)

好吧,我问了一个问题后几分钟就找到了答案。真讽刺。

如果有人需要,我将在这里发布。

您只需要将Setter添加到服务/存储库的装饰器中,并测试具有模拟集的实现即可,以代替依赖项。

赞:

装饰器:

@Setter
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<>(songCoauthorService.findByAuthorId(dto.getId())));
    author.setSongs(new HashSet<>(songService.findByAuthorId(dto.getId())));
    return author;
  }

  @Override
  public Author map(UniversalCreateDTO dto) {
    var author = delegate.map(dto);
    author.setSongs(new HashSet<>());
    author.setCoauthorSongs(new HashSet<>());
    author.setId(Constants.DEFAULT_ID);
    return author;
  }
}

测试:

@ExtendWith(MockitoExtension.class)
@SpringBootTest(classes = { StkSongbookApplication.class, AuthorMapperImpl.class })
class AuthorMapperTest {

  @Mock
  private SongService songService;

  @Mock
  private SongCoauthorService songCoauthorService;

  @Autowired
  private AuthorMapperImpl impl;

  private AuthorMapper mapper;

  @BeforeEach
  void setUp() {
    impl.setSongCoauthorService(songCoauthorService);
    impl.setSongService(songService);
    mapper = impl;
  }

  @Test
  void testMapToDTO() {
    Author author = new Author();
    author.setId(1L);
    author.setName("dummy name");
    author.setSongs(new HashSet<>());
    author.setCoauthorSongs(new HashSet<>());

    AuthorDTO dto = mapper.map(author);

    assertEquals(author.getName(), dto.getName());
    assertEquals(author.getId(), dto.getId());
  }

  @Test
  void testMapToEntity() {
    AuthorDTO author = AuthorDTO.builder().id(1L).name("dummy name").build();

    Song song1 = new Song();
    song1.setId(1L);
    song1.setTitle("title song1");

    given(songService.findByAuthorId(1L)).willReturn(List.of(new Song[]{song1}));

    Author mapped = mapper.map(author);

    assertEquals(author.getId(), mapped.getId());
    assertEquals(author.getName(), mapped.getName());
    assertEquals(1, mapped.getSongs().size());
  }
}