模型映射器适用于实时代码,但在 JUNIT 期间不起作用

Model Mapper works on Live Code but is not working during JUNITs

背景

我有一个简单的 SpringBoot 应用程序,我在其中测试从 DTO 到我的域对象的更新。当然 - 我正在使用 ModelMapper 从 DTO->Entity 进行转换。我 运行 关注的问题是,虽然 ModelMapper 在实时 运行 中工作得很好,但它在 JUNIT 期间不工作。在 JUNIT 和 LIVE 运行 期间,我在我的配置文件的 initBaseModelMapper 中放置了一个断点,断点成功命中。但在 JUNITS 中,在实际映射期间 - null 值仍在应用于域实体,但在实时 运行 期间没有应用,这完美地工作。

配置

@Configuration
public class ModelMapperConfiguration {
    @Bean(name = "myEntityMapper")
    public ModelMapper modelMapper() {
        return initBaseModelMapper();
    }
    
    public static ModelMapper initBaseModelMapper() {
        ModelMapper modelMapper = new ModelMapper();
        modelMapper.getConfiguration().setPropertyCondition(Conditions.isNotNull());
        modelMapper.getConfiguration().setSkipNullEnabled(true); // Tried without this as well
        return modelMapper; // Gets hit during LIVE and JUNITS
    }
}

主要Class 待测方法

public class MyCaseService {
    @Autowired
    @Qualifier("myEntityMapper")
    private ModelMapper modelMapper;

    @Override
    @Transactional
    public @ResponseBody
    MyCaseEntity updateMyCase(
            @Valid final String myCaseId,
            @Valid MyCaseDTO myCase) throws Exception {

        MyCaseEntity existingEntity = entityRepository.find(myCaseId);
        modelMapper.map(myCase, existingEntity);
        return existingEntity;
    }

JUNIT

我在 ModelConfiguration 中放置了一个断点,我可以看到它正在初始化,就像代码 运行 正在运行时一样。但是,出于某种原因,ModelMapper 忽略了空字段的跳过,这与 运行ning live

不同
@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(classes= {ModelMapperConfiguration.class})
public class MyCaseServiceTest {
    @InjectMocks
    private MyCaseService testSubject;

    @Spy
    @Qualifier("myEntityMapper")
    private ModelMapper modelMapper;
   
    @Before
    public void setUp() {
        // Initialized `testEntityCase` etc with Id etc
    }

    @Test
    public void testUpdate() throws Exception {
        Mockito.when(entityRepository.find(Mockito.any())).thenReturn(testEntityCase);
        
        MyCaseEntity myCase = testSubject.updateMyCase(
                "1", 
                testCaseDTO);
        
        assertEquals(1L, myCase.getId().longValue()); // <- Test Fails with NullPointer. Id becomes null during  JUNIT.
    }

克服这些问题的一种方法是自动装配私有成员的 MyCaseService 的构造函数

public class MyCaseService {

    private ModelMapper modelMapper;

    @Autowired 
    MyCaserService(@Qualifier("myEntityMapper") ModelMapper modelMapper) {
        this.modelMapper = modelMapper;
    }

    @Override
    @Transactional
    public @ResponseBody
    MyCaseEntity updateMyCase(
            @Valid final String myCaseId,
            @Valid MyCaseDTO myCase) throws Exception {

        MyCaseEntity existingEntity = entityRepository.find(myCaseId);
        modelMapper.map(myCase, existingEntity);
        return existingEntity;
    }
}

在测试中您可以使用 Spy 创建服务

@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(classes= {ModelMapperConfiguration.class})
public class MyCaseServiceTest {

    @Spy
    @Qualifier("myEntityMapper")
    private ModelMapper modelMapper;

    private MyCaseService testSubject;
   
    @Before
    public void setUp() {
        testSubject = new MyCaseService(modelMapper);
        // Initialized `testEntityCase` etc with Id etc
    }
...