Platinum Partner
java,enterprise-integration,spring mvc,testing,architecture,junit,rest,tips and tricks

JUnit Testing REST Services and Spring MVC

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 {{ articles[0].authors[0].realName }}, DZone MVB. (source)

Opinions expressed by DZone contributors are their own.

{{ tag }}, {{tag}},

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}
{{ parent.authors[0].realName || parent.author}}

{{ parent.authors[0].tagline || parent.tagline }}

{{ parent.views }} ViewsClicks
Tweet

{{parent.nComments}}