Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/rest/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 模型映射器在实时代码上工作,但在JUNITs期间不工作_Java_Rest_Modelmapper - Fatal编程技术网

Java 模型映射器在实时代码上工作,但在JUNITs期间不工作

Java 模型映射器在实时代码上工作,但在JUNITs期间不工作,java,rest,modelmapper,Java,Rest,Modelmapper,背景 我有一个简单的SpringBoot应用程序,我在其中测试从DTO到域对象的更新。自然-我正在使用ModelMapper从DTO->Entity转换。我遇到的问题是,虽然ModelMapper在实时运行中工作得很好,但在JUNITs期间却不工作。在JUNIT和实时运行期间,我在配置文件的initBaseModelMapper中放置了一个断点,断点成功命中。但是在JUNITS中,在实际的映射过程中,null值仍然应用于域实体,但在实际运行过程中没有应用,因为它工作得很好 配置 @Configu

背景

我有一个简单的SpringBoot应用程序,我在其中测试从DTO到域对象的更新。自然-我正在使用ModelMapper从DTO->Entity转换。我遇到的问题是,虽然ModelMapper在实时运行中工作得很好,但在JUNITs期间却不工作。在JUNIT和实时运行期间,我在配置文件的
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中那样自动连接)谢谢。这似乎简单而合乎逻辑-不知道为什么我没有考虑构造师迪:)欣赏它!很高兴我能帮助!