Java 模型映射器在实时代码上工作,但在JUNITs期间不工作
背景 我有一个简单的SpringBoot应用程序,我在其中测试从DTO到域对象的更新。自然-我正在使用ModelMapper从DTO->Entity转换。我遇到的问题是,虽然ModelMapper在实时运行中工作得很好,但在JUNITs期间却不工作。在JUNIT和实时运行期间,我在配置文件的Java 模型映射器在实时代码上工作,但在JUNITs期间不工作,java,rest,modelmapper,Java,Rest,Modelmapper,背景 我有一个简单的SpringBoot应用程序,我在其中测试从DTO到域对象的更新。自然-我正在使用ModelMapper从DTO->Entity转换。我遇到的问题是,虽然ModelMapper在实时运行中工作得很好,但在JUNITs期间却不工作。在JUNIT和实时运行期间,我在配置文件的initBaseModelMapper中放置了一个断点,断点成功命中。但是在JUNITS中,在实际的映射过程中,null值仍然应用于域实体,但在实际运行过程中没有应用,因为它工作得很好 配置 @Configu
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
}
}
测试中的主类方法
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会忽略空字段的跳过,这与它在运行时不同
@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.
}
@RunWith(SpringRunner.class)
@春靴测试
@ContextConfiguration(类={ModelMapperConfiguration.class})
公共类MyCaseServiceTest{
@注射模拟
私人MyCaseService测试主题;
@间谍
@限定词(“myEntityMapper”)
私有模型映射器模型映射器;
@以前
公共作废设置(){
//已初始化'testEntityCase'等,Id为etc
}
@试验
public void testUpdate()引发异常{
Mockito.when(entityRepository.find(Mockito.any())。然后返回(testEntityCase);
MyCaseEntity myCase=testSubject.updateMyCase(
"1",
testCaseDTO);
assertEquals(1L,myCase.getId().longValue());//克服这些问题的一种方法是自动连接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
}
...
我认为您有两个模型映射器,一个是由应用程序启动和Spy创建的,将在测试中使用。请尝试在Spy on安装程序中设置skipNull,或者在不使用spy@turo你是对的。Spy正在注入它自己的。但是我更喜欢JUNIT来模拟应用程序启动模式配置。原因是明天如果有人出错如果我在JUNIT中重写它,我认为测试会通过,但它将错过捕获代码错误的要点。为什么JUNIT不在测试类中提供的ContextConfiguration
中使用预初始化的ModelMapper引导呢?同样没有Spy不会工作,因为ModelMapper不会被注入MyCaseService testSubject
@Spy
创建一个新的、未初始化的ModelMapper,而这个ModelMapper随后将被自动连接,这就是Spy的用途。似乎您的配置没有创建服务,因此没有自动连接,只有Mock/Spy被注入rough@InjectMocks
@Turo谢谢。这真的让我思考,我花了一天的时间试图找到一个替代方案。我无法完全启动我的应用程序,所以我只是在我的OP中注入配置。但我确实需要同样的间谍来拦截呼叫,否则我将被迫在我的JUnit中复制ModelMapperConfiguration这很糟糕。如果明天有人更改Live ModelMapperConfiguration-JUNITs不会反映这些,因为我在测试中复制了mapper配置。正在寻找替代方案(即你100%正确-测试服务不像OP中那样自动连接)谢谢。这似乎简单而合乎逻辑-不知道为什么我没有考虑构造师迪:)欣赏它!很高兴我能帮助!