Enterprise Integration Zone is brought to you in partnership with:

Enterprise Architect in HCL Technologies a $7Billion IT services organization. My role is to work as a Technology Partner for large enterprise customers providing them low cost opensource solutions around Java, Spring and vFabric stack. I am also working on various projects involving, Cloud base solution, Mobile application and Business Analytics around Spring and vFabric space. Over 23 yrs, I have build repository of technologies and tools I liked and used extensively in my day to day work. In this blog, I am putting all these best practices and tools so that it will help the people who visit my website. Krishna is a DZone MVB and is not an employee of DZone and has posted 64 posts at DZone. You can read more from them at their website. View Full User Profile

JUnit Testing REST Services and Spring MVC

12.24.2012
| 8230 views |
  • submit to reddit
For people in a hurry get the latest code in Github and run “mvn test”

Introduction

There is a good comparison of Webservices and REST here. REST Services are a point-to-point communication over HTTP using XML. There are a couple of good discussions around this in this Stackoverflow article and Toolbox article.

Spring MVC is a good framework to develop REST Services. In this blog I will show you how JUnit tests REST Services. I started reading a few materials around spring-test-mvc and testing Spring MVC REST Services. The GET was working, but the POST was not working. You can see that in the JUnit test in the sample. Next I started trying MockHttpServletRequest/ MockHttpServletResponse there is a good material in Stacktrace on JUnit testing Spring MVC and REST Services. I followed the steps, but it still did not work. It was throwing an exception related to PropertyEditor. There was a good article on how to get this error fixed. Once I put in this fix it started working.

Details: JUnit for Spring MVC and REST Services

In this example, we developed a REST Service and Spring MVC, which has 5 operations, getAll, findbyId, create, update, delete and we write a JUnit test to call each operation and assert for the expected value.

Based on TDD, we write the test first and for all the 5 methods.  Then we assert for expected values as below,

@Test
public void testGetLoanRequest() throws Exception {
LoanRequest loanRequest1 = new LoanRequest();
loanRequest1.setId(2);
ibatisTemplate.insert("GoSmarter.loanRequestInsert", loanRequest1);
requestMock.setMethod("GET");
requestMock.setRequestURI("/loanrequests/2");
handlerAdapter.handle(requestMock, responseMock, loanRequestController);
logger.debug(responseMock.getContentAsString());
LoanRequest loanRequest = mapper.readValue(responseMock.getContentAsString(), LoanRequest.class);
assertNotNull(loanRequest);
assertEquals(loanRequest.getId(), Integer.valueOf(2));
}

@Test
public void testListLoanRequest() throws Exception {
LoanRequest loanRequest1 = new LoanRequest();
ibatisTemplate.insert("GoSmarter.loanRequestInsert", loanRequest1);
loanRequest1 = new LoanRequest();
loanRequest1.setId(2);
ibatisTemplate.insert("GoSmarter.loanRequestInsert", loanRequest1);
requestMock.setMethod("GET");
requestMock.setRequestURI("/loanrequests");
handlerAdapter.handle(requestMock, responseMock, loanRequestController);
List loanRequests = mapper.readValue(responseMock.getContentAsString(), List.class);
assertNotNull(loanRequests);
assertEquals(loanRequests.size(), 2);
}

@Test
public void testCreateLoanRequest() throws Exception {
requestMock.setMethod("POST");
String jsonPcUser = mapper.writeValueAsString(loanRequest);
logger.debug(jsonPcUser);
requestMock.setRequestURI("/loanrequests/create/" + jsonPcUser );
handlerAdapter.handle(requestMock, responseMock, loanRequestController);
logger.debug(responseMock.getContentAsString());
assertEquals(responseMock.getContentAsString(), "true");
}

@Test
public void testListLoanUpdate() throws Exception {
requestMock.setMethod("POST");
LoanRequest loanRequest1 = new LoanRequest();
ibatisTemplate.insert("GoSmarter.loanRequestInsert", loanRequest1);
loanRequest1.setCustomerName("krishna prasad");
String jsonPcUser = mapper.writeValueAsString(loanRequest1);
logger.debug(jsonPcUser);
requestMock.setRequestURI("/loanrequests/update/" + jsonPcUser );
handlerAdapter.handle(requestMock, responseMock, loanRequestController);
logger.debug(responseMock.getContentAsString());
assertEquals(responseMock.getContentAsString(), "true");
LoanRequest loanRequest2 = (LoanRequest) ibatisTemplate.queryForObject(
"GoSmarter.loanRequestDetails", 1);
assertEquals(loanRequest2.getCustomerName(), "krishna prasad");
}

@Test
public void testListLoanDelete() throws Exception {
LoanRequest loanRequest1 = new LoanRequest();
ibatisTemplate.insert("GoSmarter.loanRequestInsert", loanRequest1);
requestMock.setMethod("POST");
requestMock.setRequestURI("/loanrequests/delete/1" );
handlerAdapter.handle(requestMock, responseMock, loanRequestController);
List loanRequests = (List) ibatisTemplate
.queryForList("GoSmarter.loanRequestList");
assertEquals(loanRequests.size(), 0);
}

If you see we need to setup the AnnotationMethodHandlerAdapter and setup MappingJacksonHttpMessageConverter. as below,

@Before
public void setUp() {
requestMock = new MockHttpServletRequest();
requestMock.setContentType(MediaType.APPLICATION_JSON_VALUE);
requestMock.setAttribute(HandlerMapping.INTROSPECT_TYPE_LEVEL_MAPPING, Boolean.FALSE);

responseMock = new MockHttpServletResponse();

handlerAdapter = new AnnotationMethodHandlerAdapter();
HttpMessageConverter[] messageConverters = {new MappingJacksonHttpMessageConverter()};
handlerAdapter.setMessageConverters(messageConverters);

mapper = new ObjectMapper();
loanRequest = new LoanRequest();
}

Once we do the setup, we need to add a InitBinder method in the controller as below,

public class LoanRequestController {
@InitBinder
public void initBinder(WebDataBinder b) {
b.registerCustomEditor(LoanRequest.class, new LoanRequestEditor());
}
}

public class LoanRequestEditor extends PropertyEditorSupport {
ObjectMapper mapper = new ObjectMapper();

@Override
public void setAsText(String text) throws IllegalArgumentException {
LoanRequest obj = mapper.readValue(text, LoanRequest.class);
setValue(obj);
}

@Override
public String getAsText() {
return getValue().toString();
}
}

Conclusion

In the above example, we used MockHttpServletRequest and MockHttpServletResponse to do Junit test of REST Services and Spring MVC.

I hope it helped.



Published at DZone with permission of Krishna Prasad, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)