如何测试在 Spring Boot 中使用 Mapstruct 映射器的服务 class 方法?

How to test Service class methods which uses Mapstruct mappers in Springboot?

@Mapper(uses = SomeMapper.class,imports = Date.class)
public interface DomainModelMapper {    
    Model domainToModel(Domain domain);
    
    @Mapping(target="dateUpdated", source="dateUpdated" ,defaultExpression = "java(Date.from(java.time.OffsetDateTime.now().toInstant()))")
    @Mapping(target="id.key",source="id.key",defaultExpression = "java(com.datastax.driver.core.utils.UUIDs.timeBased())")
    Domain modelToDomain(Model model);
}

我有一个映射器 class 可以进行一些日期转换

public class SomeMapper {

    public Date OffsetDateTimeToDate(OffsetDateTime offsetDateTime) {
        return offsetDateTime != null ? Date.from(offsetDateTime.toInstant()):null;
    }

    public OffsetDateTime DateToOffsetDateTime(Date date) {
        return date != null ? date.toInstant().atOffset(ZoneOffset.UTC) : null;
    }
}

这是我的服务class,我在其中使用 DomainModelMapper

@Service
public class SomeServiceImpl implements SomeService {
    
    @Autowired
    someRepository someRepository;
    
    
    private final DomainModelMapper domainToModelMapper = 
            Mappers.getMapper(DomainModelMapper.class);

    @Override
    public Model saveSomething(Model model) {
        return DomainModelMapper.domainToModel(someRepository
                .save(DomainModelMapper.modelToDomain(model)));
    }

如何对 saveSomething(Model model) 方法进行单元测试?我如何注入 Mapstruct classes 或模拟它们?

如果您将 @Mapper 接口作为基于 Spring 的组件模型,那么它可以通过 @Autowired 注释自动装配。在 4.2. Using dependency injection

阅读更多内容
@Mapper(uses = SomeMapper.class,imports = Date.class, componentModel = "spring")
public interface DomainModelMapper { 
    // IMPLEMENTATION
}
@Service
public class SomeServiceImpl implements SomeService {
    
    @Autowired
    SomeRepository someRepository;
    
    @Autowired
    DomainModelMapper domainModelMapper;

    // THE REST OF THE IMPLEMENTATION
}

测试变得相当容易,因为所有 beans 也可以使用 @Autowired 注释注入 @SpringBootTest

  • DomainModelMapper 可以自动装配并按原样在单元测试中使用,并依赖于它的实现
  • SomeRepository 应该使用 @MockBean 来模拟,它会覆盖现有的 bean,或者如果该类型的 none 存在则创建一个新的 bean...或者像实现中那样自动装配如果您在测试阶段使用内存数据库,例如 H2。

无论如何,测试class将准备好进行测试。

@SpringBootTest
public class SomeServiceTest {
    
    @Autowired // or @MockBean
    SomeRepository someRepository;
    
    @Autowired // no need to mock it
    DomainModelMapper domainModelMapper;

    @Test
    public void test() {
        // TEST
    }
}