spring、springmvc 是java开发中的万能胶水粘合剂,不像之前普通java工程,写完代码要测试。简单,来个main 方法加 System.out.println 。
于是乎,spring项目的单元测试就没人重视了,基本上测试功能都是通过部署在tomcat或jetty上来进行的,费时费力 。。。
有没方法来方便我们进行测试呢, 答案是肯定的。
下面我们假设N种场景,来指出怎么快速接入测试。
开发环境,我们有Junit 框架(这个就不详细阐述了,资料一堆堆)。以下均假设 applicationContext.xml
是spring配置文件,spring-mvc.xml 为mvc配置文件。
sevice 以及dao等测试demo
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
import com.fly.hbn.model.Country;
import com.fly.hbn.service.CountryService;
@Transactional
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"/applicationContext.xml"})
public class CountryServiceTest
{
private static final Logger LOGGER = LoggerFactory.getLogger(CountryServiceTest.class);
@Autowired
CountryService countryService;
@Autowired
ApplicationContext applicationContext;
@Before
public void before()
{
LOGGER.info("★★★★★★★★ ApplicationContext = {}", applicationContext);
int i = 1;
for (String beanName : applicationContext.getBeanDefinitionNames())
{
LOGGER.info("{}.\t{}", i, beanName);
i++;
}
}
/**
* 事务测试(去掉@Transactional数据被插入)
*
* @see [类、类#方法、类#成员]
*/
@Test
public void testTrans()
{
for (Country it : countryService.getAllCountries())
{
// 解决异常 org.hibernate.PersistentObjectException: detached entity passed to persist
// 实体中指定了主键生成策略,主键就不能设置了,一旦不为空或者0就被认为是已经保存到了数据库中
// 一旦调用持久化方法就会抛出上面的异常。
it.setId(0);
countryService.addCountry(it);
}
}
@Test
public final void testGetAllCountries()
{
List data = countryService.getAllCountries();
LOGGER.info("{}", data);
}
@Test
public final void testGetCountry()
{
Country country = countryService.getCountry(1);
LOGGER.info("{}", country);
}
@Test
public final void testAddCountry()
{
}
@Test
public final void testUpdateCountry()
{
}
@Test
public final void testDeleteCountry()
{
}
}
controller 测试demo
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.web.context.WebApplicationContext;
@WebAppConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"/applicationContext.xml", "/spring-mvc.xml"})
public class RestControllerTest
{
private static final Logger LOGGER = LoggerFactory.getLogger(RestControllerTest.class);
@Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
@Before
public void setup()
{
mockMvc = webAppContextSetup(wac).build();
LOGGER.info("★★★★★★★★ WebApplicationContext = {}", wac);
int i = 1;
for (String beanName : wac.getBeanDefinitionNames())
{
LOGGER.info("{}.\t{}", i, beanName);
i++;
}
}
/**
* 测试 RestAPI
*
* @throws Exception
*
* @see [类、类#方法、类#成员]
*/
@Test
public void testRestAPI()
throws Exception
{
// get、post
mockMvc.perform(get("/get/1")).andDo(MockMvcResultHandlers.print());
mockMvc.perform(post("/get/1")).andDo(MockMvcResultHandlers.print());
}
}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.GenericXmlApplicationContext;
import com.fly.dao.TMeasureDAO;
import com.fly.service.TMeasureService;
import com.fly.service.UsersService;
/**
*
* MainRun
*
* @author 00fly
* @version [版本号, 2018-09-11]
* @see [相关类/方法]
* @since [产品/模块版本]
*/
public class MainRun
{
private static final Logger LOGGER = LoggerFactory.getLogger(MainRun.class);
/**
* 测试Main
*
* @param args
* @see [类、类#方法、类#成员]
*/
public static void main(String[] args)
{
GenericXmlApplicationContext context = new GenericXmlApplicationContext();
context.setValidating(false);
context.load("applicationContext.xml");
context.refresh();
LOGGER.info("★★★★★★★★ ApplicationContext = {}", context);
int i = 1;
for (String beanName : context.getBeanDefinitionNames())
{
LOGGER.info("{}.\t{}", i, beanName);
i++;
}
UsersService usersService = context.getBean(UsersService.class);
TMeasureService measureService = context.getBean(TMeasureService.class);
TMeasureDAO tMeasureDAO = context.getBean(TMeasureDAO.class);
usersService.queryAll();
measureService.queryAll();
tMeasureDAO.selectAll();
context.close();
}
}
程序大家一看就懂,本地跑绝对没问题。 可服务器上怎么跑呢?
第一步: 编译打包,上传服务器。 保证所有的class文件以及依赖jar均已经上传。目录结构类似与下面:
我们连上服务器,cd到classes 目录下,执行命令
java -Djava.ext.dirs=../lib com.fly.main.MainRun
com.fly.main.MainRun 为main全路径
方法2:jsp中调用 ,代码同main方法中类似
<%@page import="org.springframework.context.ApplicationContext"%>
<%@page import="org.springframework.web.context.support.WebApplicationContextUtils"%>
<%
ApplicationContext content = WebApplicationContextUtils.getWebApplicationContext(application);
int i = 1;
for (String beanName : content.getBeanDefinitionNames())
{
out.println(i + "." + beanName + "
");
i++;
}
%>
最后给出在spring项目中,获取HttpServletRequest 、 servletContext 、WebApplicationContext 的常见代码
WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();
ServletContext servletContext = webApplicationContext.getServletContext();
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
public class HttpContextUtils
{
public static HttpServletRequest getHttpServletRequest()
{
return ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
}
}
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
*
* 获取ApplicationContext和Bean的工具类
*
* @author 00fly
* @version [版本号, 2018年9月26日]
* @see [相关类/方法]
* @since [产品/模块版本]
*/
@Component
public class SpringContext implements ApplicationContextAware
{
private static ApplicationContext context = null;
@Override
public void setApplicationContext(ApplicationContext applicationContext)
{
context = applicationContext;
}
/**
* 根据bean的class来查找对象
*
* @param clazz
* @return
* @see [类、类#方法、类#成员]
*/
public static T getBean(Class clazz)
{
return context.getBean(clazz);
}
}
结束!