Spring3 and REST Integration(IV)Controller JUnit Test and Mock/Servlet

Spring3 and REST Integration(IV)Controller JUnit Test and Mock/Servlet

There are 4 different ways to JUnit our REST style JSON data Controller.
Servlet Mock
The first way is to use Servlet Mock. There are 2 base classes needed in our project
The Mock Web Application Loader class will be like these:
package com.sillycat.easyrestserver.core;

import javax.servlet.ServletException;

import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.SourceFilteringListener;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.io.FileSystemResourceLoader;
import org.springframework.mock.web.MockServletConfig;
import org.springframework.mock.web.MockServletContext;
import org.springframework.test.context.MergedContextConfiguration;
import org.springframework.test.context.support.AbstractContextLoader;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.XmlWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

public class MockWebApplicationContextLoader extends AbstractContextLoader {

MockWebApplication configuration;

static MockServletContext servletContext;

static MockServletConfig servletConfig;

static XmlWebApplicationContext webApplicationContext;

public ApplicationContext loadContext(
MergedContextConfiguration mergedConfig) throws Exception {
servletConfig = new MockServletConfig(servletContext,
configuration.name());
servletContext = new MockServletContext(configuration.webapp(),
new FileSystemResourceLoader());
webApplicationContext = new XmlWebApplicationContext();
webApplicationContext.getEnvironment().setActiveProfiles(
mergedConfig.getActiveProfiles());
servletContext.setAttribute(
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,
webApplicationContext);
webApplicationContext.setServletConfig(servletConfig);
webApplicationContext.setConfigLocations(configuration.locations());

prepareWebApplicationContext();

return webApplicationContext;
}

public ApplicationContext loadContext(String... locations) throws Exception {
servletConfig = new MockServletConfig(servletContext,
configuration.name());
servletContext = new MockServletContext(configuration.webapp(),
new FileSystemResourceLoader());
webApplicationContext = new XmlWebApplicationContext();
servletContext.setAttribute(
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,
webApplicationContext);
webApplicationContext.setServletConfig(servletConfig);
webApplicationContext.setConfigLocations(locations);
prepareWebApplicationContext();
return webApplicationContext;
}

private void prepareWebApplicationContext() throws ServletException {
@SuppressWarnings("serial")
final DispatcherServlet dispatcherServlet = new DispatcherServlet() {
protected WebApplicationContext createWebApplicationContext(
ApplicationContext parent) {
return webApplicationContext;
}
};
webApplicationContext
.addBeanFactoryPostProcessor(new BeanFactoryPostProcessor() {
public void postProcessBeanFactory(
ConfigurableListableBeanFactory beanFactory) {
beanFactory.registerResolvableDependency(
DispatcherServlet.class, dispatcherServlet);
}
});
webApplicationContext
.addApplicationListener(new SourceFilteringListener(
webApplicationContext,
new ApplicationListener<ContextRefreshedEvent>() {
public void onApplicationEvent(
ContextRefreshedEvent event) {
dispatcherServlet.onApplicationEvent(event);
}
}));
webApplicationContext.refresh();
webApplicationContext.registerShutdownHook();
dispatcherServlet.setContextConfigLocation("");
dispatcherServlet.init(servletConfig);
}

protected String[] generateDefaultLocations(Class<?> clazz) {
extractConfiguration(clazz);
return super.generateDefaultLocations(clazz);
}

protected String[] modifyLocations(Class<?> clazz, String... locations) {
extractConfiguration(clazz);
return super.modifyLocations(clazz, locations);
}

private void extractConfiguration(Class<?> clazz) {
configuration = AnnotationUtils.findAnnotation(clazz,
MockWebApplication.class);
if (configuration == null) {
throw new IllegalArgumentException("Test class " + clazz.getName()
+ " must be annotated @MockWebApplication.");
}
}

protected String getResourceSuffix() {
return "-context.xml";
}
}


And we will use the mockwebapplication class to hold our annotation configuration:
package com.sillycat.easyrestserver.core;

import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface MockWebApplication {
String webapp() default "src/main/webapp";

String name();

String[] locations() default "src/test/test-content.xml";
}


The test class will be like this:
package com.sillycat.easyrestserver.controller;

import java.io.IOException;

import javax.servlet.ServletException;

import org.codehaus.jackson.map.ObjectMapper;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.HandlerMapping;

import com.sillycat.easyrestserver.core.MockWebApplication;
import com.sillycat.easyrestserver.core.MockWebApplicationContextLoader;
import com.sillycat.easyrestserver.model.Company;
import com.sillycat.easyrestserver.model.Person;

/**
* mock the servlet and use servlet to test our controller
* servlet.service(mockRequest, mockResponse);
* can not mock the service or manager in controller
* @author karl
*
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = MockWebApplicationContextLoader.class)
@MockWebApplication(name = "easyrestserver", locations = "classpath:test-context.xml")
public class PersonControllerTest1 {

@Autowired
private DispatcherServlet servlet;

ObjectMapper mapper;
Person person;
MockHttpServletRequest mockRequest;
MockHttpServletResponse mockResponse;

@Before
public void setUp() throws ServletException, IOException {
MockitoAnnotations.initMocks(this);
mapper = new ObjectMapper();
person = new Person();
person.setCompany(new Company());
person.setId(1);
person.setPersonName("person1");

mockRequest = new MockHttpServletRequest();
mockRequest.setAttribute(HandlerMapping.INTROSPECT_TYPE_LEVEL_MAPPING,true);

mockResponse = new MockHttpServletResponse();
}


@Test
public void get() throws Exception {
mockRequest.setMethod("GET");
mockRequest.setRequestURI("/person/1");
mockRequest.setContentType(MediaType.APPLICATION_JSON_VALUE);
mockResponse = new MockHttpServletResponse();

servlet.service(mockRequest, mockResponse);

Person actualPerson = mapper.readValue(
mockResponse.getContentAsString(), Person.class);
Assert.assertEquals(actualPerson.getId(), person.getId());
}

@Test
public void add() throws Exception{
mockRequest.setContentType(MediaType.APPLICATION_JSON_VALUE);
mockRequest.setMethod("POST");
mockRequest.setRequestURI("/person");

String jsonPerson = mapper.writeValueAsString(person);
mockRequest.setContent(jsonPerson.getBytes());

servlet.service(mockRequest, mockResponse);

Assert.assertEquals(mockResponse.getStatus(), 200);
Person actualPerson = mapper.readValue(
mockResponse.getContentAsString(), Person.class);
Assert.assertEquals(actualPerson.getId(), person.getId());
}
}


The sample project named easyrestserver.

references:
spring 3 and rest
http://hi.baidu.com/luohuazju/blog/item/1fe358ea5da873c0d539c9b4.html
http://hi.baidu.com/luohuazju/blog/item/c380b67f9946421b28388ab7.html
http://hi.baidu.com/luohuazju/blog/item/3b68f609650a37dc3bc763c5.html

tcpdump on mac
http://support.apple.com/kb/HT3994
http://hi.baidu.com/luohuazju/blog/item/da079eb3de7109b2d9335aa5.html

mock test
http://www.iteye.com/topic/828513
http://stackoverflow.com/questions/9138555/spring-framework-test-restful-web-service-controller-offline-i-e-no-server-n
http://stackoverflow.com/questions/1401128/how-to-unit-test-a-spring-mvc-controller-using-pathvariable/2457902#2457902
http://ted-young.googlecode.com/svn/trunk/blog.spring-mvc-integration-testing/
https://github.com/springside/springside4/blob/master/examples/mini-service/src/test/java/org/springside/examples/miniservice/webservice/ws/AccountWebServiceTest.java
https://github.com/SpringSource/spring-test-mvc
http://elf8848.iteye.com/blog/875830
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值