The web application I wrote works as expected. Now I want to unit-test the Controller methods. The pattern for these methods is:
For the conversion steps 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;
@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.
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?
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. 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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.