在Spring中整合JUnit单元测试

简介:

一 简介

在Java Web开发中,通常我们会开发很多的功能代码。在代码正式使用之前,为了确保代码能够正确实现我们预期的功能,最好是添加一些简单代码对代码逻辑进行测试。很显然,JUnit就是一个不错的单元测试工具,同时在Spring中我们也可以很方便地引入JUnit进行测试

二 代码实例

(1)引入必需的jar包:

这里除了Spring以及其他模块所需要的jar包之外,还需要引入:

  • spring-test-4.2.3.RELEASE.jar

  • junit-4.10.jar

注:jar包版本使用最新稳定版即可

(2)测试项目目录结构以及配置:

wKiom1gJt7KRXgJTAABa3rIuBM0102.png

上面图中的一些目录是我自己新建的,为的就是将不同功能的文件分隔开。这个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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
< web-app  xmlns = "http://xmlns.jcp.org/xml/ns/javaee"  xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
       http://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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
<? xml  version = "1.0"  encoding = "UTF-8" ?>
< beans  xmlns = "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/beans 
             http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
             http://www.springframework.org/schema/jee 
             http://www.springframework.org/schema/jee/spring-jee-4.0.xsd
             http://www.springframework.org/schema/aop 
             http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
             http://www.springframework.org/schema/context 
             http://www.springframework.org/schema/context/spring-context-4.0.xsd
             http://www.springframework.org/schema/cache  
              http://www.springframework.org/schema/cache/spring-cache-4.0.xsd  
             http://www.springframework.org/schema/tx 
             http://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" >
 
     < bean  id = "propertyConfigurer"
         class = "org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" >
         < property  name = "locations" >
             < list >
                 < value >classpath:jdbc.properties</ value >
             </ list >
         </ property >
     </ bean >
 
     <!-- Druid连接池,文档:https://github.com/alibaba/druid/wiki/常见问题 -->
     < bean  id = "dataSource"  class = "com.alibaba.druid.pool.DruidDataSource"
         destroy-method = "close" >
         <!-- 数据库基本信息配置 -->
         < property  name = "url"  value = "${url}"  />
         < property  name = "username"  value = "${username}"  />
         < property  name = "password"  value = "${password}"  />
         < property  name = "driverClassName"  value = "${driverClassName}"  />
         < property  name = "filters"  value = "${filters}"  />
         <!-- 最大并发连接数 -->
         < property  name = "maxActive"  value = "${maxActive}"  />
         <!-- 初始化连接数量 -->
         < property  name = "initialSize"  value = "${initialSize}"  />
         <!-- 配置获取连接等待超时的时间 -->
         < property  name = "maxWait"  value = "${maxWait}"  />
         <!-- 最小空闲连接数 -->
         < property  name = "minIdle"  value = "${minIdle}"  />
         <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
         < property  name = "timeBetweenEvictionRunsMillis"  value = "${timeBetweenEvictionRunsMillis}"  />
         <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
         < property  name = "minEvictableIdleTimeMillis"  value = "${minEvictableIdleTimeMillis}"  />
         < property  name = "validationQuery"  value = "${validationQuery}"  />
         < property  name = "testWhileIdle"  value = "${testWhileIdle}"  />
         < property  name = "testOnBorrow"  value = "${testOnBorrow}"  />
         < property  name = "testOnReturn"  value = "${testOnReturn}"  />
         < property  name = "maxOpenPreparedStatements"  value = "${maxOpenPreparedStatements}"  />
         <!-- 打开 removeAbandoned 功能 -->
         < property  name = "removeAbandoned"  value = "${removeAbandoned}"  />
         <!-- 1800 秒,也就是 30 分钟 -->
         < property  name = "removeAbandonedTimeout"  value = "${removeAbandonedTimeout}"  />
         <!-- 关闭 abanded 连接时输出错误日志 -->
         < property  name = "logAbandoned"  value = "${logAbandoned}"  />
     </ bean >
 
     <!-- MyBatis相关配置 -->
     < bean  id = "sqlSessionFactory"  class = "org.mybatis.spring.SqlSessionFactoryBean" >
         < property  name = "configLocation"  value = "classpath:context/sql-map-config.xml"  />
         < property  name = "dataSource"  ref = "dataSource"  />
     </ bean >
     < bean  class = "org.mybatis.spring.mapper.MapperScannerConfigurer" >
         < property  name = "basePackage"  value = "cn.zifangsky.mapper"  />
         < property  name = "sqlSessionFactoryBeanName"  value = "sqlSessionFactory"  />
     </ bean >
 
     < bean  id = "sqlSessionTemplate"  class = "org.mybatis.spring.SqlSessionTemplate" >
         < constructor-arg  index = "0"  ref = "sqlSessionFactory"  />
     </ bean >
 
     <!-- 事务相关配置 -->
     < bean  id = "transactionManager"
         class = "org.springframework.jdbc.datasource.DataSourceTransactionManager" >
         < property  name = "dataSource"  ref = "dataSource"  />
     </ bean >
 
     < tx:annotation-driven  transaction-manager = "transactionManager"  />
</ beans >

注:jdbc.properties文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
url: jdbc:mysql://localhost:3306/cookie_db
driverClassName: com.mysql.jdbc.Driver
username: root
password: root
filters: stat,wall
maxActive: 100
initialSize: 10
maxWait: 60000
minIdle: 10
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 123
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
maxOpenPreparedStatements: 20
removeAbandoned: true
removeAbandonedTimeout: 1800
logAbandoned: true

(3)新建测试的DAO层的代码:

由于我这里使用的是Mybatis,因此就直接使用“mybatis-generator”插件自动生成一些基本文件了

注:关于“mybatis-generator”插件的使用想了解更多可以参考我的这篇文章:https://www.zifangsky.cn/431.html

(4)单元测试示例:

在src/test/java目录下新建TestUserTable.java,其内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package  cn.zifangsky.test.base;
 
import  org.junit.Test;
import  org.junit.runner.RunWith;
import  org.springframework.beans.factory.annotation.Autowired;
import  org.springframework.test.context.ContextConfiguration;
import  org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
import  cn.zifangsky.mapper.UserMapper;
import  cn.zifangsky.model.User;
import  junit.framework.Assert;
 
@RunWith (SpringJUnit4ClassRunner. class )
@ContextConfiguration (locations={ "classpath:/context/context.xml" })
public  class  TestUserTable {
     @Autowired
     UserMapper userMapper;
     
     @Test
     public  void  testSelectByPrimaryKey(){
         User user = userMapper.selectByPrimaryKey( 1 );
         
//      System.out.println(user.getName());
         Assert.assertEquals( "admin" , user.getName());   //预期值-实际值
     }
 
}

关于这里的代码我简单解释下:

  1. @RunWith注解配置了此次测试使用的环境

  2. @ContextConfiguration注解配置了基本的Spring配置文件的路径

  3. UserMapper 是一个具体的DAO层的类,使用@Autowired注解自动注入到这个单元测试中

  4. @Test注解标注的方法被当做一个测试方法,里面的内容随意。当然,这里仅仅只是测试了根据主键查询一个实体

  5. junit.framework.Assert 这个类可以用于断言,这里就是判断从数据库中查出来的用户名是否为“admin” 。如果是,那么此次测试成功,如果不是则测试失败。如果不习惯这种写法的话还可以使用我注释掉的那样直接在控制台中打印一些数据,然后我们再手动判断

(5)运行单元测试:

关于单元测试,可以有以下几种方式来运行测试,分别是:

  1. 在标注了@Test注解的方法上鼠标右键选择:Run As –> JUnit Test ,这种方式测试的就是这一个方法

  2. 在一个单元测试的Java类上鼠标右键选择JUnit单元测试,这种方式测试的是这个类中的所有标有@Test注解的方法

  3. 在一个包或者一个目录上选择JUnit单元测试。很显然,这种方式的测试的实例更多

如果一个方法测试成功,那么在JUnit视图中是这样的:

wKiom1gJuCTwRHf1AABVtPGuLDs604.png

相反,测试失败显示的视图是这样的:

wKiom1gJuD6CVm9UAACPnGo5lnc311.png



本文转自 pangfc 51CTO博客,原文链接:http://blog.51cto.com/983836259/1864248,如需转载请自行联系原作者

相关文章
|
1月前
|
XML Java 测试技术
Spring5入门到实战------17、Spring5新功能 --Nullable注解和函数式注册对象。整合JUnit5单元测试框架
这篇文章介绍了Spring5框架的三个新特性:支持@Nullable注解以明确方法返回、参数和属性值可以为空;引入函数式风格的GenericApplicationContext进行对象注册和管理;以及如何整合JUnit5进行单元测试,同时讨论了JUnit4与JUnit5的整合方法,并提出了关于配置文件加载的疑问。
Spring5入门到实战------17、Spring5新功能 --Nullable注解和函数式注册对象。整合JUnit5单元测试框架
|
6天前
|
SQL JavaScript 前端开发
基于Java访问Hive的JUnit5测试代码实现
根据《用Java、Python来开发Hive应用》一文,建立了使用Java、来开发Hive应用的方法,产生的代码如下
25 6
|
6天前
|
JavaScript 前端开发 Java
Spring Boot+cucumber+契约测试
Spring Boot+cucumber+契约测试
7 0
Spring Boot+cucumber+契约测试
|
6天前
|
Java 数据库连接 数据格式
【Java笔记+踩坑】Spring基础2——IOC,DI注解开发、整合Mybatis,Junit
IOC/DI配置管理DruidDataSource和properties、核心容器的创建、获取bean的方式、spring注解开发、注解开发管理第三方bean、Spring整合Mybatis和Junit
【Java笔记+踩坑】Spring基础2——IOC,DI注解开发、整合Mybatis,Junit
|
29天前
|
测试技术
单元测试问题之使用TestMe时利用JUnit 5的参数化测试特性如何解决
单元测试问题之使用TestMe时利用JUnit 5的参数化测试特性如何解决
21 2
|
29天前
|
Java 测试技术 Maven
单元测试问题之在Maven项目中引入JUnit 5和Mockito的依赖如何解决
单元测试问题之在Maven项目中引入JUnit 5和Mockito的依赖如何解决
89 1
|
19天前
|
测试技术 Java Spring
Spring 框架中的测试之道:揭秘单元测试与集成测试的双重保障,你的应用真的安全了吗?
【8月更文挑战第31天】本文以问答形式深入探讨了Spring框架中的测试策略,包括单元测试与集成测试的有效编写方法,及其对提升代码质量和可靠性的重要性。通过具体示例,展示了如何使用`@MockBean`、`@SpringBootTest`等注解来进行服务和控制器的测试,同时介绍了Spring Boot提供的测试工具,如`@DataJpaTest`,以简化数据库测试流程。合理运用这些测试策略和工具,将助力开发者构建更为稳健的软件系统。
27 0
|
28天前
|
测试技术
如何使用 JUnit 测试方法是否存在异常
【8月更文挑战第22天】
14 0
|
29天前
|
Java 测试技术 Maven
Junit单元测试 @Test的使用教程
这篇文章是一个关于Junit单元测试中`@Test`注解使用的教程,包括在Maven项目中添加Junit依赖、编写带有@Test注解的测试方法,以及解决@Test注解不生效的常见问题。
|
1月前
|
前端开发 Java 测试技术
单元测试问题之在Spring MVC项目中添加JUnit的Maven依赖,如何操作
单元测试问题之在Spring MVC项目中添加JUnit的Maven依赖,如何操作