Spring Junit4 测试Web应用程序

来源:互联网 发布:java.util.optional 编辑:程序博客网 时间:2024/05/22 08:13

在web项目中用junit写单元测试

      经过了3年的项目开发后,今年我终于换了一家公司,在找工作期间也不断充电,看了看书,什么敏捷开发之类的,且不谈敏捷开发方式,单说一下其中需要用到的单元测试这一条,我认为的确有用,只是看过了有关敏捷开发的书之后才知道,原来单元测试不仅是做测试用的,因为自己总认为自己是开发人员,不是做测试的,因此对不是开发的活就不感兴趣了,实际上,单元测试的用途除了用于测试系统某个部分的功能正常外,还有帮助开发人员进行代码重构的功能以及可以作为学习api的功能等。

      进入新公司后,由于一开始并不很紧,我就琢磨着把单元测试引入到项目中来,吃一回螃蟹。但是第一次做并不容易,如果仅仅是做某个类的某个方法的单元测试应该很简单,只要写一个XXXTest类,继承TestCase类就可以了,然后就去写断言,但是实际工作中,我是在一个spring+hibernate的web工程中进行开发的,工程中的类都是由spring注入的,数据库层也都是通过spring+hibernate集成的,因此又遇到如何得到spring中的bean的问题,在项目中不让上网,因此只能抽空上网搜一堆东西去看,其实spring也集成了junit进来,org.springframework.test包中就有可以用于测试spring中的类的接口、抽象类等。

       在项目中,我继承了org.springframework.test.AbstractDependencyInjectionSpringContextTests类,这个类的作用就是可以使继承了这个类的子类得到需要的spring中配置的bean。代码示例如下:

Java代码  收藏代码
  1. import org.springframework.context.ConfigurableApplicationContext;  
  2. import org.springframework.test.AbstractDependencyInjectionSpringContextTests;  
  3.   
  4. /** 
  5.  *  
  6.  * 测试抽象类,所有本项目中需要从spring得到bean的测试类均需继承 
  7.  *  
  8.  */  
  9. public class AbstractTest extends AbstractDependencyInjectionSpringContextTests {  
  10.   
  11.     /** 
  12.      * 如有其他需要初始化的变量,可以覆盖本方法 
  13.      */  
  14.     public void initVariables() {  
  15.   
  16.     }  
  17.   
  18.     public void onSetUp() {  
  19.         initProject();//初始化项目的参数  
  20.     }  
  21.   
  22.     public void initProject() {  
  23.         ConfigurableApplicationContext ac = this.applicationContext;  
  24.         com.mycompany.core.util.SpringBeansGetter.wac = ac;  
  25.         ParameterManager.CACHE = false;  
  26.   
  27.         // - 配置文件路径设置 -------------------------  
  28.         ParameterManager.PARAMETER = "file:WebRoot/WEB-INF/classes/Parameters.xml";  
  29.     }  
  30.   
  31.     public String[] getConfigLocations() {  
  32.         String[] configLocations = {  
  33.                 "classpath:spring/context-adapter.xml",  
  34.                 "classpath:spring/context-app.xml",  
  35.                 "classpath:spring/context-base.xml",  
  36.                 "classpath:spring/context-pub.xml",  
  37.                 "classpath:spring/context-task.xml" };  
  38.         return configLocations;  
  39.     }  
  40.   
  41.     /** 
  42.      * 得到spring中的bean 
  43.      *  
  44.      * @param beanId 
  45.      * @return 
  46.      */  
  47.     public Object getBean(String beanId) {  
  48.         Object bean = com.mycompany.core.util.SpringBeansGetter.getBean(beanId);  
  49.         return bean;  
  50.     }  
  51. }  

      继承AbstractDependencyInjectionSpringContextTests 类后,需要覆盖getConfigLocations方法,在这个方法中把需要得到bean的spring配置文件的位置放入数组中即可,onSetUp方法类似于junit中的setUp方法。由于项目中有一些地方我们采用的是通过spring上下文得到bean的方式,通过覆盖getConfigLocations方法就可以初始化上下文,从而得到bean。

      在具体写单元测试的时候,我只要继承我AbstractTest类,就可以得到spring配置中的bean,进行单元测试了,示例一下:

Java代码  收藏代码
  1. package cn.mycompany.mdms.scheduler.service;  
  2.   
  3. import java.text.ParseException;  
  4. import java.util.Map;  
  5.   
  6. import org.quartz.CronTrigger;  
  7. import org.quartz.Scheduler;  
  8. import org.quartz.SchedulerException;  
  9. import org.quartz.Trigger;  
  10.   
  11. import cn.mycompany.mdms.AbstractTest;  
  12.   
  13. /** 
  14.  * AutoScanServiceImpl测试类 
  15.  *  
  16.  */  
  17. public class SchedulerServiceImplTest extends AbstractTest {  
  18.     ISchedulerService schedulerService;  
  19.     Scheduler scheduler;  
  20.   
  21.     public void initVariables() {  
  22.         scheduler = (Scheduler) getBean("scheduler");  
  23.         schedulerService = (ISchedulerService) getBean("schedulerService");  
  24.     }  
  25.   
  26.   
  27.     public void testGetSchedulerStates() throws SchedulerException,  
  28.             ParseException {  
  29.         Map schedulerStates = schedulerService.getSchedulerStates();  
  30.         JobTriggerVo jobTriggerVo = (JobTriggerVo) schedulerStates  
  31.                 .get("monitorDirJob-autoscan");  
  32.         String[] triggerStates = jobTriggerVo.getTriggerStates();  
  33.         Trigger[] triggersOfJob = jobTriggerVo.getTriggersOfJob();  
  34.         this.logger.info("" + triggerStates.length);  
  35.         this.logger.info(schedulerStates.keySet());  
  36.     }  
  37. }  

       解决了在web工程中通过spring得到bean的问题,在工程中写单元测试就和给普通的类写单元测试类似了,其实spring还提供了其他一些测试抽象类用于继承,网上很好找到相关介绍,我这里罗列一下:

Java代码  收藏代码
  1. 1、AbstractSpringContextTests类[1],该类全部方法是protected的,  
  2. 通常不使用这个类,而使用它的子类们  
  3. 2、AbstractDependencyInjectionSpringContextTests类[2]:继承于类[1]:名字N长的。  
  4. 如果仅仅使用Spring依赖注入功能,可以让测试用例继承该类。  
  5. 3、AbstractTransactionalSpringContextTests类[3]:继承于类[2],  
  6. 继承该类的测试用例在spring管理的事务中进行,测试完后对数据库的记录不会造成任何影响。  
  7. 你对数据库进行一些操作后,它会自动把数据库回滚,这样就保证了你的测试对于环境没有任何影响  
  8. 4、AbstractTransactionalDataSourceSpringContextTests:继承于类[3],  
  9. 功能更强大,用于测试持久层组件,看其源代码,  
  10. 有一行"protected JdbcTemplate jdbcTemplate;",提供了一个JdbcTemplate的变量,  
  11. 通过该对象可以直接操作数据库。  

      通过引入单元测试,我在开发中的确体会到了重构和单元测试的关系,通过编写单元测试可以大大提高重构代码的效率,当然首先保证了代码质量。估计航天系统也是通过一项项的单元测试作为基础才能有把握的进行下一步设计、组装。

0 0
原创粉丝点击