Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/12.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 如何模拟Spring转换服务?_Java_Spring_Unit Testing_Mockito - Fatal编程技术网

Java 如何模拟Spring转换服务?

Java 如何模拟Spring转换服务?,java,spring,unit-testing,mockito,Java,Spring,Unit Testing,Mockito,我编写的web应用程序工作正常。现在我想对控制器方法进行单元测试。这些方法的模式是: 将http请求对象(DTO)转换为域对象 使用域对象调用服务层中的业务逻辑 将业务逻辑的响应转换为响应(DTO)对象 对于转换步骤,我使用Spring ConversionService,bean配置如下: <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean

我编写的web应用程序工作正常。现在我想对控制器方法进行单元测试。这些方法的模式是:

  • 将http请求对象(DTO)转换为域对象
  • 使用域对象调用服务层中的业务逻辑
  • 将业务逻辑的响应转换为响应(DTO)对象
  • 对于转换步骤,我使用Spring ConversionService,bean配置如下:

    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
      <list>
        <bean class="my.package.RequestToDomainConverter" />
        <bean class="my.package.DomainToResponseConverter" />
      </list>
    </property>
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @WebAppConfiguration
    @ContextConfiguration(locations={"classpath:/my/package/MyControllerTest-context.xml"})
    public class MyControllerTest {
        private MockMvc mockMvc;
    
        @Mock
        private ConversionService conversionService;
    
        @Mock
        private BusinessLayer businessLayer;
    
        @InjectMocks
        private MyController myController;
    
        @Before
        public void setup() throws Exception {
            MockitoAnnotations.initMocks(this);
            mockMvc = MockMvcBuilders.standaloneSetum(myController).build();
        }
    
        @Test
        public void testCreateSelection(){
            // create a json string representation of the requestDTO
            String jsonDTO = new String("a valid json representation");
    
            // create objects to convert
            RequestDTO myRequestDTO = new RequestDTO();
            DomainObject myDomainObject = new DomainObject();
            ResponseDTO responseDTO = new ResponseDTO();
    
            // instruct the conversionservice mock to return the expected objects
            when(conversionService.convert(myRequestDTO, DomainObject.class))
                .thenReturn(myDomainObject);
            when(conversionService.convert(domainResponse, ResponseDTO.class))
                .thenReturn(myResponseDTO);
    
            // the businessLayer mock returns the same object that was given to it
            when(businessLayer.doService(domainObject))
                .thenReturn(domainObject);
    
            //create the necessary http headers
            HttHeaders httpHeaders = new HttpHeaders();
            httpHeaders.add("Accept", "application/json");
    
            //execute the controller method
            mockMvc.perform(post("/selection")
                .content(jsonDTO)
                .contentType(MediaType.APPLICATION_JSON)
                .headers(httpHeaders))
            .andExpect(status().isOk());
            // further testing...
        }
    }
    
    使用方法如下:

    @RequestMapping(method  =  RequestMethod.POST,
                    headers = "Accept=application/json")
    @ResponseStatus(value = HttpStatus.CREATED) 
    @ResponseBody 
    public ResponseDTO createSelection( 
        @RequestBody RequestDTO requestDTO,
        HttpServletResponse response,
        Authentication authentication ) {
    
        DomainObject domainObject = conversionService.convert(requestDTO, DomainObject.class);
        // note: during test the conversionService returns null here...
        DomainObject businessAnswer = BusinessLayer.doService(domainObject);
        ResponseDTO responseDTO = conversionService.convert(businessAnswer, ResponseDTO.class);
    return responseDTO;
    }
    
    如上所述,当部署到应用程序服务器时,应用程序按预期工作

    我的测试类构建如下:

    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
      <list>
        <bean class="my.package.RequestToDomainConverter" />
        <bean class="my.package.DomainToResponseConverter" />
      </list>
    </property>
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @WebAppConfiguration
    @ContextConfiguration(locations={"classpath:/my/package/MyControllerTest-context.xml"})
    public class MyControllerTest {
        private MockMvc mockMvc;
    
        @Mock
        private ConversionService conversionService;
    
        @Mock
        private BusinessLayer businessLayer;
    
        @InjectMocks
        private MyController myController;
    
        @Before
        public void setup() throws Exception {
            MockitoAnnotations.initMocks(this);
            mockMvc = MockMvcBuilders.standaloneSetum(myController).build();
        }
    
        @Test
        public void testCreateSelection(){
            // create a json string representation of the requestDTO
            String jsonDTO = new String("a valid json representation");
    
            // create objects to convert
            RequestDTO myRequestDTO = new RequestDTO();
            DomainObject myDomainObject = new DomainObject();
            ResponseDTO responseDTO = new ResponseDTO();
    
            // instruct the conversionservice mock to return the expected objects
            when(conversionService.convert(myRequestDTO, DomainObject.class))
                .thenReturn(myDomainObject);
            when(conversionService.convert(domainResponse, ResponseDTO.class))
                .thenReturn(myResponseDTO);
    
            // the businessLayer mock returns the same object that was given to it
            when(businessLayer.doService(domainObject))
                .thenReturn(domainObject);
    
            //create the necessary http headers
            HttHeaders httpHeaders = new HttpHeaders();
            httpHeaders.add("Accept", "application/json");
    
            //execute the controller method
            mockMvc.perform(post("/selection")
                .content(jsonDTO)
                .contentType(MediaType.APPLICATION_JSON)
                .headers(httpHeaders))
            .andExpect(status().isOk());
            // further testing...
        }
    }
    
    在调试模式下运行此测试时,我看到已成功调用控制器中的createSelection方法,而在该方法中,requestDTO对象具有给定给jsonDTO对象的值

    但是,当要求conversionService将requestDTO转换为DomainObject时,它返回null


    这是为什么?如何设置我的测试以使其返回转换的对象?

    这是因为在下面的行中:

    when(conversionService.convert(myRequestDTO, DomainObject.class))
            .thenReturn(myDomainObject);
    
    方法希望接收相同的对象
    myRequestDTO
    ,这与您的情况不同,因为您将在控制器内部创建同一类的另一个实例。两者都是从同一个类创建的,但具有不同的标识。相反,您可以使用:

    when(conversionService.convert(any(DomainObject.class), Matchers.<DomainObject>any()))
            .thenReturn(myDomainObject);
    
    when(conversionService.convert(any(DomainObject.class)、Matchers.any())
    .thenReturn(myDomainObject);
    
    这允许期望相同的对象,而与此对象的标识无关