2015-03-03 2 views
1

Веб-приложение, которое я написал, работает, как и ожидалось. Теперь я хочу, чтобы модулировать тестовые методы. Шаблон для этих методов:Как насмехаться с Spring ConversionService?

  1. Преобразование запроса HTTP объект (DTO) для объекта домена
  2. объект Использование домена для вызова бизнес-логики в слое службы
  3. Преобразовать реакцию бизнес-логики в ответ (DTO) объект

Для этапов преобразования я использую Spring ConversionService, боб сконфигурирован следующим образом:

<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> 

Этот боб Autowired в мой контроллер:

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

Однако обращение к конверсии возвращает null, когда его просят преобразовать requestDTO в объект DomainObject.

Почему это и как настроить мой тест, чтобы он возвращал преобразованный объект?

ответ

3

Это происходит потому, что в строке ниже:

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

Метод рассчитывают получить тот же объект myRequestDTO, который ваш случай отличается тем, что внутри вашего контроллера вы создадите еще один экземпляр того же класса. Оба были созданы из одного класса, но имеют различную идентичность. Вместо этого вы можете использовать:

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

Это позволяет ожидать того же объекта, это не имеет значения личность этого объекты

Смежные вопросы