如何模拟Spring ConversionService



我编写的web应用程序按预期工作。现在我想对Controller方法进行单元测试。这些方法的模式是:

  1. 将http请求对象(DTO)转换为域对象
  2. 使用域对象调用服务层中的业务逻辑
  3. 将业务逻辑的响应转换为响应(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>

这个bean自动连接到我的控制器:

@Autowired
ConversionService conversionService;

并像这样使用:

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

如上所述,当部署到应用程序服务器时,应用程序将按预期工作。

我的测试类构建如下:

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

这允许期望相同的对象,这与该对象的身份无关

相关内容

  • 没有找到相关文章