zoukankan      html  css  js  c++  java
  • Spring单元测试

       1.基于AbstractDependencyInjectionSpringContextTests

      Spring的单元测试可以使用AbstractDependencyInjectionSpringContextTests做测试,不支持事务。AbstractTransactionalDataSourceSpringContextTests是支持事务的。

      Spring单元测试需要注意的地方:

      (1)需要注入的类内成员如果不是public类型,需要定义setter方法才能正常注入(针对在Spring配置中不重复的类,如果重复出现则需要使用getBean方法);

      (2)需要引入Spring-test.jar到工程,才能继承该测试类;

      (3)默认的classpath在WEB-INF/classes/目录下,如果Spring配置文件不在该目录下需要指定位置(设置classpath或者使用项目根目录);

      (4)如果测试类比较多,可以使用一个公共的测试基类完成注入的工作。

        (5) 需要一个getConfigLocations方法指定配置文件路径。

    public class Test extends AbstractDependencyInjectionSpringContextTests {
        @Autowired
        private PersonService personService;
        public PersonService getPersonService() {
            return personService;
        }
        
        protected String[] getConfigLocations() {
            String[] configs = new String[] { "/Iocbean.xml"};
            return configs;
        }
    
        public void setPersonService(PersonService personService) {
            this.personService = personService;
        }
        
        public void test(){
            personService.save();
        }
    }

     2.基于JUnit的测试

       单元测试目前主要的框架包括 Junit、TestNG,还有些 MOCK 框架,例如 Jmock、Easymock、PowerMock 等。 

    public class AOPTestJunit {
        private AService aService;    
        private ApplicationContext ctx;
        
        
        public AService getaService() {
            return aService;
        }
    
        public void setaService(AService aService) {
            this.aService = aService;
        }
    
    
        @Before
        public void setUp() throws Exception {
            ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        }
    
        @After
        public void tearDown() throws Exception {
        }
    
        @Test
        public void test() {
            System.out.println("SpringTest JUnit test");
            aService = (AService) ctx.getBean("aService");
            aService.fooA("JUnit test fooA");
            aService.barA();
        }
    
    }

      3.基于注解的方式

      第2中方法的测试类中,我们还不能使用 Spring 的注解方式,会出现空指针异常,要实现注解方式的自动注入要使用如下的方式。   

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("/spring-jms.xml")
    @Transactional
    public class ProducerConsumerTest {
     
        @Autowired
        private ProducerService producerService;
        @Autowired
        @Qualifier("queueDestination")
        private Destination destination;
        
        @Test
        public void testSend() {
            for (int i=0; i<2; i++) {
                producerService.sendMessage(destination, "你好,生产者!这是消息:" + (i+1));
            }
        }
        
    } 

    对标签的解释:

    @RunWith 注释标签是 Junit 提供的,用来说明此测试类的运行者,这里用了 SpringJUnit4ClassRunner,这个类是一个针对 Junit 运行环境的自定义扩展,用来标准化在 Spring 环境中 Junit的测试用例,例如支持的注释标签。

    @ContextConfiguration 注释标签是 Spring test context 提供的,用来指定 Spring 配置信息的来源,支持指定 XML 文件位置或者 Spring 配置类名,这里我们指定 classpath 下的 /spring-jms.xml 为配置文件的位置。

    @Transactional 注释标签是表明此测试类的事务启用,这样所有的测试方案都会自动的 rollback,即不用自己清除自己所做的任何对数据库的变更了。

     

    一些常见的基于 Junit4 的注释标签在 Spring 测试环境中的使用方法:

    @Test(expected=...)

    此注释标签的含义是,这是一个测试,期待一个异常的发生,期待的异常通过 xxx.class 标识。例如,我们修改 AccountService.Java 的 insertIfNotExist 方法,对于传入的参数如果为空,则抛出 IllegalArgumentException,如下:

     public void insertIfNotExist(Account account) {

              if(account==null)

                        throw new IllegalArgumentException("account is null");

              Account acct = accountDao.getAccountById(account.getId());

              if(acct==null) {

                        log.debug("No "+account+" found,would insert it.");

                        accountDao.saveAccount(account);

              }

              acct = null;

     }

    然后,在测试类中增加一个测试异常的方法,如下:

     @Test(expected=IllegalArgumentException.class)

     public void testInsertException() {

              service.insertIfNotExist(null);

     }

    运行结果是 green bar。

     

    @Test(timeout=...)

    可以给测试方法指定超时时间(毫秒级别),当测试方法的执行时间超过此值,则失败。

    比如在 AccountService 中增加如下方法:

     public void doSomeHugeJob() {

         try {

            Thread.sleep(2*1000);

         } catch (InterruptedException e) {

         }

     }

    上述方法模拟任务执行时间 2 秒,则测试方法如下:

     @Test(timeout=3000)

     public void testHugeJob() {

         service.doSomeHugeJob();

     }

    上述测试方法期待 service.doSomeHugeJob 方法能在 3 秒内结束,执行测试结果是 green bar。

    @Repeat

    通过 @Repeat,您可以轻松的多次执行测试用例,而不用自己写 for 循环,使用方法:

     @Repeat(3)

     @Test(expected=IllegalArgumentException.class)

     public void testInsertException() {

         service.insertIfNotExist(null);

     }

    这样,testInsertException 就能被执行 3 次。

  • 相关阅读:
    第03组 Alpha冲刺(3/4)
    第03组 Alpha冲刺(2/4)
    第03组 Alpha冲刺(1/4)
    课程总结
    第十四周学习总结&实验报告
    第十三周课程总结
    第十二周学习总结
    第十一周课程总结
    第十周课程总结
    第九周课程总结&实验报告(七)
  • 原文地址:https://www.cnblogs.com/lnlvinso/p/4000479.html
Copyright © 2011-2022 走看看