mardi 3 mars 2015

How to mock Spring ConversionService

The web application I wrote works as expected. Now I want to unit-test the Controller methods. The pattern for these methods is:



  1. Convert the http request object (DTO) to domain object

  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


For the conversion I use the Spring ConversionService, a bean configured as follows:



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



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

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

//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());
}
}


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.


However, the conversionService returns null when asked to convert the requestDTO to a DomainObject.


Why is this, and how to set up my test to have it return the converted object?


Aucun commentaire:

Enregistrer un commentaire