spring mvc 代码测试那些事儿

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());
    }
}

  • 服务器环境
    场景一:后台框架完工、服务器准备好了java环境、数据库也ok了,某模块完工了,小激动,想丢到服务器上偷偷跑下功能,怎么办?
    方法1, 祭出我们的main方法。

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均已经上传。目录结构类似与下面:
spring mvc 代码测试那些事儿_第1张图片
我们连上服务器,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);
    }
}

结束!

你可能感兴趣的:(Spring)