在Spring中整合JUnit单元测试
在Java Web开发中,通常我们会开发很多的功能代码。在代码正式使用之前,为了确保代码能够正确实现我们预期的功能,最好是添加一些简单代码对代码逻辑进行测试。很显然,JUnit就是一个不错的单元测试工具,同时在Spring中我们也可以很方便地引入JUnit进行测试
二 代码实例(1)引入必需的jar包:
这里除了Spring以及其他模块所需要的jar包之外,还需要引入:
spring-test-4.2.3.RELEASE.jar
junit-4.10.jar
注:jar包版本使用最新稳定版即可
(2)测试项目目录结构以及配置:
上面图中的一些目录是我自己新建的,为的就是将不同功能的文件分隔开。这个Demo项目采用的技术是:Spring + Spring MVC + Mybatis + MySQL +Druid连接池
context.xml文件是一些基本配置;springmvc-servlet.xml文件是 Spring MVC相关的配置;sql-map-config.xml文件是Mybatis相关配置。下面我粘贴下web.xml文件和context.xml文件的代码供大家参考,其他的一些配置文件跟这里关系不大就不粘贴出来了
i)web.xml:
<web-appxmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaeehttp://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"version="3.1"><context-param><param-name>contextConfigLocation</param-name><param-value>classpath:context/context.xml</param-value></context-param><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><listener><listener-class>org.springframework.web.context.request.RequestContextListener</listener-class></listener><servlet><servlet-name>springmvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:context/springmvc-servlet.xml</param-value></init-param><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>springmvc</servlet-name><!--<url-pattern>*.html</url-pattern>--><url-pattern>*.html</url-pattern></servlet-mapping><filter><filter-name>characterEncodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param></filter><filter-mapping><filter-name>characterEncodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><servlet><servlet-name>DruidStatView</servlet-name><servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class></servlet><servlet-mapping><servlet-name>DruidStatView</servlet-name><url-pattern>/druid/*</url-pattern></servlet-mapping><filter><filter-name>druidWebStatFilter</filter-name><filter-class>com.alibaba.druid.support.http.WebStatFilter</filter-class><init-param><param-name>exclusions</param-name><param-value>/public/*,*.js,*.css,/druid*,*.jsp,*.swf</param-value></init-param><init-param><param-name>principalSessionName</param-name><param-value>sessionInfo</param-value></init-param><init-param><param-name>profileEnable</param-name><param-value>true</param-value></init-param></filter><filter-mapping><filter-name>druidWebStatFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping></web-app>
ii)context.xml:
<?xmlversion="1.0"encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:cache="http://www.springframework.org/schema/cache"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:jee="http://www.springframework.org/schema/jee"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-4.0.xsdhttp://www.springframework.org/schema/jeehttp://www.springframework.org/schema/jee/spring-jee-4.0.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-4.0.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.0.xsdhttp://www.springframework.org/schema/cachehttp://www.springframework.org/schema/cache/spring-cache-4.0.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-4.0.xsd"xmlns:context="http://www.springframework.org/schema/context"xmlns:tx="http://www.springframework.org/schema/tx"xmlns:aop="http://www.springframework.org/schema/aop"><beanid="propertyConfigurer"class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"><propertyname="locations"><list><value>classpath:jdbc.properties</value></list></property></bean><!--Druid连接池,文档:https://github.com/alibaba/druid/wiki/常见问题--><beanid="dataSource"class="com.alibaba.druid.pool.DruidDataSource"destroy-method="close"><!--数据库基本信息配置--><propertyname="url"value="${url}"/><propertyname="username"value="${username}"/><propertyname="password"value="${password}"/><propertyname="driverClassName"value="${driverClassName}"/><propertyname="filters"value="${filters}"/><!--最大并发连接数--><propertyname="maxActive"value="${maxActive}"/><!--初始化连接数量--><propertyname="initialSize"value="${initialSize}"/><!--配置获取连接等待超时的时间--><propertyname="maxWait"value="${maxWait}"/><!--最小空闲连接数--><propertyname="minIdle"value="${minIdle}"/><!--配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒--><propertyname="timeBetweenEvictionRunsMillis"value="${timeBetweenEvictionRunsMillis}"/><!--配置一个连接在池中最小生存的时间,单位是毫秒--><propertyname="minEvictableIdleTimeMillis"value="${minEvictableIdleTimeMillis}"/><propertyname="validationQuery"value="${validationQuery}"/><propertyname="testWhileIdle"value="${testWhileIdle}"/><propertyname="testOnBorrow"value="${testOnBorrow}"/><propertyname="testOnReturn"value="${testOnReturn}"/><propertyname="maxOpenPreparedStatements"value="${maxOpenPreparedStatements}"/><!--打开removeAbandoned功能--><propertyname="removeAbandoned"value="${removeAbandoned}"/><!--1800秒,也就是30分钟--><propertyname="removeAbandonedTimeout"value="${removeAbandonedTimeout}"/><!--关闭abanded连接时输出错误日志--><propertyname="logAbandoned"value="${logAbandoned}"/></bean><!--MyBatis相关配置--><beanid="sqlSessionFactory"class="org.mybatis.spring.SqlSessionFactoryBean"><propertyname="configLocation"value="classpath:context/sql-map-config.xml"/><propertyname="dataSource"ref="dataSource"/></bean><beanclass="org.mybatis.spring.mapper.MapperScannerConfigurer"><propertyname="basePackage"value="cn.zifangsky.mapper"/><propertyname="sqlSessionFactoryBeanName"value="sqlSessionFactory"/></bean><beanid="sqlSessionTemplate"class="org.mybatis.spring.SqlSessionTemplate"><constructor-argindex="0"ref="sqlSessionFactory"/></bean><!--事务相关配置--><beanid="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><propertyname="dataSource"ref="dataSource"/></bean><tx:annotation-driventransaction-manager="transactionManager"/></beans>
注:jdbc.properties文件:
url:jdbc:mysql://localhost:3306/cookie_dbdriverClassName:com.mysql.jdbc.Driverusername:rootpassword:rootfilters:stat,wallmaxActive:100initialSize:10maxWait:60000minIdle:10timeBetweenEvictionRunsMillis:60000minEvictableIdleTimeMillis:300000validationQuery:SELECT123testWhileIdle:truetestOnBorrow:falsetestOnReturn:falsemaxOpenPreparedStatements:20removeAbandoned:trueremoveAbandonedTimeout:1800logAbandoned:true
(3)新建测试的DAO层的代码:
由于我这里使用的是Mybatis,因此就直接使用“mybatis-generator”插件自动生成一些基本文件了
注:关于“mybatis-generator”插件的使用想了解更多可以参考我的这篇文章:https://www.zifangsky.cn/431.html
(4)单元测试示例:
在src/test/java目录下新建TestUserTable.java,其内容如下:
packagecn.zifangsky.test.base;importorg.junit.Test;importorg.junit.runner.RunWith;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.test.context.ContextConfiguration;importorg.springframework.test.context.junit4.SpringJUnit4Cla***unner;importcn.zifangsky.mapper.UserMapper;importcn.zifangsky.model.User;importjunit.framework.Assert;@RunWith(SpringJUnit4Cla***unner.class)@ContextConfiguration(locations={"classpath:/context/context.xml"})publicclassTestUserTable{@AutowiredUserMapperuserMapper;@TestpublicvoidtestSelectByPrimaryKey(){Useruser=userMapper.selectByPrimaryKey(1);//System.out.println(user.getName());Assert.assertEquals("admin",user.getName());//预期值-实际值}}
关于这里的代码我简单解释下:
@RunWith注解配置了此次测试使用的环境
@ContextConfiguration注解配置了基本的Spring配置文件的路径
UserMapper 是一个具体的DAO层的类,使用@Autowired注解自动注入到这个单元测试中
@Test注解标注的方法被当做一个测试方法,里面的内容随意。当然,这里仅仅只是测试了根据主键查询一个实体
junit.framework.Assert这个类可以用于断言,这里就是判断从数据库中查出来的用户名是否为“admin” 。如果是,那么此次测试成功,如果不是则测试失败。如果不习惯这种写法的话还可以使用我注释掉的那样直接在控制台中打印一些数据,然后我们再手动判断
(5)运行单元测试:
关于单元测试,可以有以下几种方式来运行测试,分别是:
在标注了@Test注解的方法上鼠标右键选择:Run As –> JUnit Test,这种方式测试的就是这一个方法
在一个单元测试的Java类上鼠标右键选择JUnit单元测试,这种方式测试的是这个类中的所有标有@Test注解的方法
在一个包或者一个目录上选择JUnit单元测试。很显然,这种方式的测试的实例更多
如果一个方法测试成功,那么在JUnit视图中是这样的:
相反,测试失败显示的视图是这样的:
PS:上面图片中的水印是我个人博客的域名,因此还请管理员手下留情不要给我标为“转载文章”,谢谢!!!
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。