Spring回顾之五 —— 测试,JUnit与SpringTest的完美结合

2024-09-06 15:18

本文主要是介绍Spring回顾之五 —— 测试,JUnit与SpringTest的完美结合,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

    没有测试的程序,是不完整的,每一个从事写程序的人员,都应该坚持做单元测试,通过单元测试可以验证程序基本功能的有效性,从而保证整个系统的质量,功在一时,利在千秋。这里我们将尝试使用Junit和SpringTest,在之前的系统里添加测试功能。

第一步:JUnit与SpringTest的引入
    JUnit故名知意,是一个专门为Java语言提供单元测试的框架。平时的开发过程中,单元测试会频繁的用到,所以在JUnit之上,Spring又做了进一步的封装,这个集成的测试模块也就是SpringTest。
    SpringTest的使用可以避免频繁、重复的容器加载,这个使用起来会有很好的体验。它还可以不用像JUnit那样通过getBean()方法去容器里获取目标元素,直接就像在实际开发中一样,做好配置,写好标签就可以得到想要的结果。SpringTest还做了对数据库操作的回滚处理,这个在日常测试使用中相当实用,可以避免去数据库做频繁修改以确保环境正常。等等诸多,SpringTest能在强大的JUnit之上让我们更加方便的进行单元测试,来先看看他们所需的依赖包,打开pom文件,在dependencies里添加以下代码

Xml代码   收藏代码
  1. <!-- ============== test begin ============== -->  
  2. <dependency><!-- JUnit单元测试框架 -->  
  3.     <groupId>junit</groupId>  
  4.     <artifactId>junit</artifactId>  
  5.     <version>4.12</version>  
  6.     <scope>test</scope>  
  7. </dependency>  
  8. <dependency><!-- spring对测试框架的简单封装功能 -->  
  9.     <groupId>org.springframework</groupId>  
  10.     <artifactId>spring-test</artifactId>  
  11.     <version>${spring.version}</version>  
  12.     <scope>test</scope>  
  13. </dependency>  
  14. <!-- ============== test end ============== -->  

    就酱,更新系统,依赖的相应jar包会添加到系统,接下来我们写程序运行运行来看看效果。

第二步:JUnit测试验证
    我们先来看看单独使用JUnit进行测试的样子,在src/test/java下,建立准备编写测试类的包,然后创建名为JunitTestUser的测试类,代码如下
Java代码   收藏代码
  1. package test.demo;  
  2.   
  3. import org.apache.ibatis.session.SqlSession;  
  4. import org.apache.ibatis.session.SqlSessionFactory;  
  5. import org.junit.Before;  
  6. import org.junit.Test;  
  7. import org.slf4j.Logger;  
  8. import org.slf4j.LoggerFactory;  
  9. import org.springframework.context.support.ClassPathXmlApplicationContext;  
  10.   
  11. import test.demo.dao.UserDAO;  
  12. import test.demo.data.User;  
  13.   
  14. public class JunitTestUser {  
  15.     private static final Logger logger = LoggerFactory.getLogger(JunitTestUser.class);  
  16.     private UserDAO userDao;  
  17.       
  18.     @Before  
  19.     public void init() {  
  20.         ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("classpath*:applicationContext.xml");  
  21.         SqlSessionFactory sqlSessionFactory = (SqlSessionFactory) classPathXmlApplicationContext.getBean("sqlSessionFactory");  
  22.         SqlSession sqlSession = sqlSessionFactory.openSession();  
  23.         userDao = sqlSession.getMapper(UserDAO.class);  
  24.         classPathXmlApplicationContext.close();  
  25.     }  
  26.     @Test  
  27.     public void testGetUserById() {  
  28.         Integer userId = 1;  
  29.         User user = userDao.getUserById(userId);  
  30.         logger.info("用户的名字是 : " + user.getName());  
  31.     }  
  32. }  
package test.demo;import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;import test.demo.dao.UserDAO;
import test.demo.data.User;public class JunitTestUser {private static final Logger logger = LoggerFactory.getLogger(JunitTestUser.class);private UserDAO userDao;@Beforepublic void init() {ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("classpath*:applicationContext.xml");SqlSessionFactory sqlSessionFactory = (SqlSessionFactory) classPathXmlApplicationContext.getBean("sqlSessionFactory");SqlSession sqlSession = sqlSessionFactory.openSession();userDao = sqlSession.getMapper(UserDAO.class);classPathXmlApplicationContext.close();}@Testpublic void testGetUserById() {Integer userId = 1;User user = userDao.getUserById(userId);logger.info("用户的名字是 : " + user.getName());}
}

    这里边顺便提一下,这里使用的ClassPathXmlApplicationContext是spring读取xml比较常用的类,也可以直接用ApplicationContext,但共同的作用都是从spring的容器中获取所需的bean,我们这里获取了配置文件中的sqlSessionFactory,然后从这个连接池冲拿到数据库会话(SqlSession),继而我们可以得到所需的dao,通过这个dao我们可以进行对数据库的操作。
    这里回顾下我们的applicationContext.xml内容,估计能帮助对这段代码的理解

Xml代码   收藏代码
  1. <?xml version="1.0" encoding="UTF-8" ?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
  4.     xmlns:context="http://www.springframework.org/schema/context"  
  5.     xmlns:p="http://www.springframework.org/schema/p"   
  6.     xmlns:aop="http://www.springframework.org/schema/aop"  
  7.     xmlns:tx="http://www.springframework.org/schema/tx"  
  8.     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd  
  9.     http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd   
  10.     http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd   
  11.     http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd ">  
  12.   
  13.     <!-- 加载配置文件 -->  
  14.     <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
  15.         <property name="location" value="classpath:jdbc.properties" />  
  16.     </bean>  
  17.     <!-- ========================= ORM BEGIN  ========================= -->  
  18.     <!-- 数据源配置 -->  
  19.     <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">  
  20.         <property name="driverClassName" value="${jdbc.driver}" />  
  21.         <property name="url" value="${jdbc.url}" />  
  22.         <property name="username" value="${jdbc.username}" />  
  23.         <property name="password" value="${jdbc.password}" />  
  24.         <!-- 初始化连接大小 -->  
  25.         <property name="initialSize" value="${jdbc.initialSize}"></property>  
  26.         <!-- 连接池最大数量 -->  
  27.         <property name="maxActive" value="${jdbc.maxActive}"></property>  
  28.         <!-- 连接池最大空闲 -->  
  29.         <property name="maxIdle" value="${jdbc.maxIdle}"></property>  
  30.         <!-- 连接池最小空闲 -->  
  31.         <property name="minIdle" value="${jdbc.minIdle}"></property>  
  32.         <!-- 获取连接最大等待时间 -->  
  33.         <property name="maxWait" value="${jdbc.maxWait}"></property>  
  34.     </bean>   
  35.     <!-- spring和MyBatis完美整合,不需要mybatis的配置映射文件,mapperLocations的设置将会自动扫描MyBatis的xml文件-->    
  36.     <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">    
  37.         <property name="dataSource" ref="dataSource"/>  
  38.         <property name="mapperLocations" value="classpath*:test/demo/mapper/*Mapper.xml"/>    
  39.     </bean>  
  40.     <!-- DAO接口所在包名,Spring会自动寻找其路径下的接口 -->    
  41.     <bean id="demoDaoFactory" class="org.mybatis.spring.mapper.MapperScannerConfigurer">    
  42.         <property name="basePackage" value="test.demo.dao" />    
  43.         <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>    
  44.     </bean>  
  45.     <!-- 数据事务管理 ( Spring允许允许 MyBatis参与到事务管理中,所以MyBatis没有特定的事务管理器,直接利用了Spring中的 DataSourceTransactionManager) -->    
  46.     <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">    
  47.         <property name="dataSource" ref="dataSource"/>  
  48.     </bean>   
  49.     <!-- ========================= ORM END  ========================= -->  
  50. </beans>   

    OK,测试部分的代码写完之后,我们直接右键,Run As ,选中Junit Test
   

    然后可以看到Eclipse的Junit栏运行之后会显示出一下的绿色条带
   

    OK,这是成功的运行了代码,测试没问题,然后我们去Console栏,打印的日志里我们可以看到如下代码
Java代码   收藏代码
  1. 16:46:14,725  INFO DruidDataSource:785 - {dataSource-1} inited  
  2. 16:46:14,900  INFO JunitTestUser:30 - 用户的名字是 : tom  
16:46:14,725  INFO DruidDataSource:785 - {dataSource-1} inited
16:46:14,900  INFO JunitTestUser:30 - 用户的名字是 : tom

    嗯,名字tom已经被打印,好,我们已经完成用JUnit做的单元测试,下边来看看加入SpringTest是什么效果。

第三步:JUnit与SpringTest共同的尝试
    紧接着我们创建一个名为SpringTestUser的测试类,代码如下
Java代码   收藏代码
  1. package test.demo;  
  2.   
  3. import javax.annotation.Resource;  
  4. import org.junit.Test;  
  5. import org.junit.runner.RunWith;  
  6. import org.slf4j.Logger;  
  7. import org.slf4j.LoggerFactory;  
  8. import org.springframework.test.context.ContextConfiguration;  
  9. import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;  
  10. import test.demo.dao.UserDAO;  
  11. import test.demo.data.User;  
  12.   
  13. @RunWith(SpringJUnit4ClassRunner.class)  
  14. @ContextConfiguration({"classpath*:applicationContext.xml"})  
  15. public class SpringTestUser {  
  16.     private static final Logger logger = LoggerFactory.getLogger(SpringTestUser.class);  
  17.       
  18.     @Resource  
  19.     private UserDAO userDao;  
  20.       
  21.     @Test  
  22.     public void testGetUserById() {  
  23.         Integer userId = 1;  
  24.         User user = userDao.getUserById(userId);  
  25.         logger.info("用户的名字是 : " + user.getName());  
  26.     }  
  27. }  
package test.demo;import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import test.demo.dao.UserDAO;
import test.demo.data.User;@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath*:applicationContext.xml"})
public class SpringTestUser {private static final Logger logger = LoggerFactory.getLogger(SpringTestUser.class);@Resourceprivate UserDAO userDao;@Testpublic void testGetUserById() {Integer userId = 1;User user = userDao.getUserById(userId);logger.info("用户的名字是 : " + user.getName());}
}

    注意标签@RunWith(SpringJUnit4ClassRunner.class)说的是我们这段代码其实用的还是JUnit进行测试的。@ContextConfiguration({"classpath*:applicationContext.xml"})以标签的形式完成对配置文件的加载,接下来看代码,简直是爽爆了,简洁明了的逻辑,只要配置文件里做好了注入的配置,这里直接通过标签获取即可,OK,我们来运行下:右键,Run As ,选中Junit Test...Junit栏运行显示已经测试成功
   

    我们去Console栏的日志里可以看到如下代码
Java代码   收藏代码
  1. 16:55:57,241  INFO DruidDataSource:785 - {dataSource-1} inited  
  2. 16:55:57,457  INFO SpringTestUser:26 - 用户的名字是 : tom  
  3. 16:55:57,459  INFO GenericApplicationContext:987 - Closing org.springframework.context.support.GenericApplicationContext@4667ae56: startup date [Wed Mar 22 16:55:56 CST 2017]; root of context hierarchy  
  4. 16:55:57,462  INFO DruidDataSource:1514 - {dataSource-1} closed  
16:55:57,241  INFO DruidDataSource:785 - {dataSource-1} inited
16:55:57,457  INFO SpringTestUser:26 - 用户的名字是 : tom
16:55:57,459  INFO GenericApplicationContext:987 - Closing org.springframework.context.support.GenericApplicationContext@4667ae56: startup date [Wed Mar 22 16:55:56 CST 2017]; root of context hierarchy
16:55:57,462  INFO DruidDataSource:1514 - {dataSource-1} closed

    OK,测试已完成!

第四步:小结
    这里不想用太多华丽的词藻来吹嘘使用SpringTest带来的便利,仅仅对比代码的就可以看出,使用SpringTest的优势。实际使用过程中SpringTest集成的对事物的处理啊,对测试数据的回滚啊,仅通过一个标签就可以实现,那可是提供了实实在在的方便,感兴趣的可以试下。




这篇关于Spring回顾之五 —— 测试,JUnit与SpringTest的完美结合的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1142370

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

性能测试介绍

性能测试是一种测试方法,旨在评估系统、应用程序或组件在现实场景中的性能表现和可靠性。它通常用于衡量系统在不同负载条件下的响应时间、吞吐量、资源利用率、稳定性和可扩展性等关键指标。 为什么要进行性能测试 通过性能测试,可以确定系统是否能够满足预期的性能要求,找出性能瓶颈和潜在的问题,并进行优化和调整。 发现性能瓶颈:性能测试可以帮助发现系统的性能瓶颈,即系统在高负载或高并发情况下可能出现的问题

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

字节面试 | 如何测试RocketMQ、RocketMQ?

字节面试:RocketMQ是怎么测试的呢? 答: 首先保证消息的消费正确、设计逆向用例,在验证消息内容为空等情况时的消费正确性; 推送大批量MQ,通过Admin控制台查看MQ消费的情况,是否出现消费假死、TPS是否正常等等问题。(上述都是临场发挥,但是RocketMQ真正的测试点,还真的需要探讨) 01 先了解RocketMQ 作为测试也是要简单了解RocketMQ。简单来说,就是一个分