简体   繁体   English

如何模拟Spring ConversionService?

[英]How to mock Spring ConversionService?

The web application I wrote works as expected. 我写的Web应用程序按预期工作。 Now I want to unit-test the Controller methods. 现在我想对Controller方法进行单元测试。 The pattern for these methods is: 这些方法的模式是:

  1. Convert the http request object (DTO) to domain object 将http请求对象(DTO)转换为域对象
  2. Use domain object to call business logic in a service layer 使用域对象在服务层中调用业务逻辑
  3. Convert the response of the business logic to a response (DTO) object 将业务逻辑的响应转换为响应(DTO)对象

For the conversion steps I use the Spring ConversionService, a bean configured as follows: 对于转换步骤,我使用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>

This bean is Autowired into my controller: 这个bean自动装入我的控制器:

@Autowired
ConversionService conversionService;

and used like this: 并像这样使用:

@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;
}

As stated above, when deployed to an application server the application works as expected. 如上所述,当部署到应用程序服务器时,应用程序按预期工作。

My test class is built as follows: 我的测试类构建如下:

@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...
    }
}

When running this test in debug mode I see that the createSelection method in my controller is successfully called, and while in the method the requestDTO object has the values that were given to the jsonDTO object. 在调试模式下运行此测试时,我看到我的控制器中的createSelection方法被成功调用,而在方法中,requestDTO对象具有给jsonDTO对象的值。

However, the conversionService returns null when asked to convert the requestDTO to a DomainObject. 但是,当要求将requestDTO转换为DomainObject时,conversionService返回null。

Why is this, and how to set up my test to have it return the converted object? 为什么这样,以及如何设置我的测试让它返回转换后的对象?

It is because in the line below: 这是因为在下面的行:

when(conversionService.convert(myRequestDTO, DomainObject.class))
        .thenReturn(myDomainObject);

Method expect to receive the same object myRequestDTO which is your case is different because inside of your controller you will create another instance of the same class. 方法期望接收相同的对象myRequestDTO ,这是你的情况不同,因为在你的控制器内你将创建同一个类的另一个实例。 Both have been created from the same class but have different identity. 两者都是从同一个类创建的,但具有不同的身份。 Instead you can use: 相反,你可以使用:

when(conversionService.convert(any(DomainObject.class), Matchers.<DomainObject>any()))
        .thenReturn(myDomainObject);

This allow to expect the same object, it doesn't matter the identity of this objects 这允许期望相同的对象,这个对象的身份并不重要

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM