JUnit是一个Java语言的单元测试框架。它由Kent Beck和Erich Gamma建立,逐渐成为源于Kent Beck的sUnit的xUnit家族中最为成功的一个。 JUnit有它自己的JUnit扩展生态圈。多数Java的开发环境都已经集成了JUnit作为单元测试的工具。
如何在spring项目中使用Junit进行单元测试?
接上一节案例,我们使用Junit实现StudentsDao的各个业务逻辑方法的测试。
1.添加Junit和spring-test依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.simoniu</groupId>
<artifactId>springbase</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<spring.version>5.2.5.RELEASE</spring.version>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
<scope>compile</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.4</version>
</dependency>
<!-- 连接到mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.35</version>
</dependency>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
2.在test目录下创建要测试的包。
比如:要测试com.dao.StudentsDao类,创建一个和测试类相同的包com.dao,如下图所示:

3.编写单元测试类StudentsDaoTest
package com.dao;
import com.entity.Students;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.context.ApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class StudentsDaoTest {
@Resource
private ApplicationContext context;
@Test
public void testStudentsDao(){
JdbcTemplate jdbcTemplate = (JdbcTemplate) context.getBean("jdbcTemplate");
//初始化数据库。
String sql = "CREATE TABLE IF NOT EXISTS `students` (\n" +
" `sid` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,\n" +
" `sname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,\n" +
" `gender` varchar(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,\n" +
" `major` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,\n" +
" PRIMARY KEY (`sid`) USING BTREE\n" +
") ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = Dynamic;";
jdbcTemplate.execute(sql);
Students s = (Students) context.getBean("s1");
StudentsDao studentsDaoImpl = (StudentsDao) context.getBean("studentsDaoImpl");
studentsDaoImpl.add(s);
studentsDaoImpl.query("S001");
List<Students> studentsList = new ArrayList<Students>();
studentsList.add(new Students("S002","郭靖","男","九阴真经"));
studentsList.add(new Students("S003","黄蓉","女","打狗棒法"));
studentsList.add(new Students("S004","段誉","男","六脉神剑"));
studentsDaoImpl.addBatch(studentsList);
List<Students> students = studentsDaoImpl.queryAll();
students.forEach(System.out::println);
s.setSname("张无忌");
studentsDaoImpl.update(s);
studentsDaoImpl.query("S001");
studentsDaoImpl.delete("S001");
students = studentsDaoImpl.queryAll();
students.forEach(System.out::println);
}
}
4.执行单元测试
选中testStudentsDao()方法,执行单元测试。运行结果如下:
环绕内的前置通知
权限的校验...
新增学生:Students{sid='S001', sname='张三丰', gender='男', major='太极拳'}
环绕内的后置通知
环绕内的最终通知
最终通知...
日志记录...
环绕内的前置通知
权限的校验...
查询学生编号:S001
Students{sid='S001', sname='张三丰', gender='男', major='太极拳'}
环绕内的后置通知
环绕内的最终通知
最终通知...
日志记录...
环绕内的前置通知
权限的校验...
环绕内的后置通知
环绕内的最终通知
最终通知...
日志记录...
环绕内的前置通知
权限的校验...
环绕内的后置通知
环绕内的最终通知
最终通知...
日志记录...
Students{sid='S001', sname='张三丰', gender='男', major='太极拳'}
Students{sid='S002', sname='郭靖', gender='男', major='九阴真经'}
Students{sid='S003', sname='黄蓉', gender='女', major='打狗棒法'}
Students{sid='S004', sname='段誉', gender='男', major='六脉神剑'}
环绕内的前置通知
权限的校验...
修改学生:Students{sid='S001', sname='张无忌', gender='男', major='太极拳'}
环绕内的后置通知
环绕内的最终通知
最终通知...
日志记录...
环绕内的前置通知
权限的校验...
查询学生编号:S001
Students{sid='S001', sname='张无忌', gender='男', major='太极拳'}
环绕内的后置通知
环绕内的最终通知
最终通知...
日志记录...
环绕内的前置通知
权限的校验...
删除学生编号:S001
环绕内的后置通知
环绕内的最终通知
最终通知...
日志记录...
环绕内的前置通知
权限的校验...
环绕内的后置通知
环绕内的最终通知
最终通知...
日志记录...
Students{sid='S002', sname='郭靖', gender='男', major='九阴真经'}
Students{sid='S003', sname='黄蓉', gender='女', major='打狗棒法'}
Students{sid='S004', sname='段誉', gender='男', major='六脉神剑'}
对于基于全注解方式,我们无需配置applicationContext.xml,单元测试类StudentsDaoTest的注解改写为如下方式:
import com.config.SpringConfiguration;
import com.entity.Students;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.context.ApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
@RunWith(SpringRunner.class)//指定Junit4使用Spring提供的测试环境
@ContextConfiguration(classes={SpringConfiguration.class})
public class StudentsDaoTest {
@Resource
private ApplicationContext context;
@Test
public void testStudentsDao(){
JdbcTemplate jdbcTemplate = (JdbcTemplate) context.getBean("jdbcTemplate");
//初始化数据库。
String sql = "CREATE TABLE IF NOT EXISTS `students` (\n" +
" `sid` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,\n" +
" `sname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,\n" +
" `gender` varchar(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,\n" +
" `major` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,\n" +
" PRIMARY KEY (`sid`) USING BTREE\n" +
") ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = Dynamic;";
jdbcTemplate.execute(sql);
Students s = (Students) context.getBean("s1");
StudentsDao studentsDaoImpl = (StudentsDao) context.getBean("studentsDaoImpl");
studentsDaoImpl.add(s);
studentsDaoImpl.query("S001");
List<Students> studentsList = new ArrayList<Students>();
studentsList.add(new Students("S002","郭靖","男","九阴真经"));
studentsList.add(new Students("S003","黄蓉","女","打狗棒法"));
studentsList.add(new Students("S004","段誉","男","六脉神剑"));
studentsDaoImpl.addBatch(studentsList);
List<Students> students = studentsDaoImpl.queryAll();
students.forEach(System.out::println);
s.setSname("张无忌");
studentsDaoImpl.update(s);
studentsDaoImpl.query("S001");
studentsDaoImpl.delete("S001");
students = studentsDaoImpl.queryAll();
students.forEach(System.out::println);
}
}
junit有以下常用注解: |注解|说明| |-|-| |@Test|表示是一个测试方法| |@Test(timeout=2000)|表示测试超时时间| |@Test(expected=IllegalArgumentException.class) |检查测试方法是不是抛出了对应的异常| |@BeforeClass|在所有测试方法之前执行,用来初始化静态属性,仅仅执行一次| |@AfterClass|在所有测试方法结束之后执行,用来销毁静态属性| |@Before|每次测试方法之前都会被执行| |@After|每次测试方法之后都会被执行| |@Ignore|该测试方法被忽略| |@RunWith|可以修改测试运行器 org.junit.runner.Runner|
规范使用junit的测试注解,上例改下如下:
@ContextConfiguration 加载 applicationContext.xml的方式。
import com.entity.Students;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.context.ApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.Assert;
import javax.annotation.Resource;
import java.util.List;
@RunWith(SpringRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class StudentDaoImplTest {
@Resource
private ApplicationContext context;
@Resource
private StudentsDao studentsDaoImpl;
@BeforeClass
public static void initStudentsTable() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
JdbcTemplate jdbcTemplate = (JdbcTemplate) context.getBean("jdbcTemplate");
String sql = "CREATE TABLE IF NOT EXISTS `students` (\n" +
" `sid` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,\n" +
" `sname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,\n" +
" `gender` varchar(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,\n" +
" `major` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,\n" +
" PRIMARY KEY (`sid`) USING BTREE\n" +
") ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = Dynamic;";
jdbcTemplate.execute(sql);
}
@Test
public void testAdd() {
try {
Students s = (Students) context.getBean("s1");
boolean flag = studentsDaoImpl.add(s);
Assert.isTrue(flag, "");
} catch (Exception ex) {
ex.printStackTrace();
}
}
@Test
public void testQueryById() {
Students s = studentsDaoImpl.query("S0001");
System.out.println(s);
}
@Test
public void testQueryAll() {
List<Students> studentsList = studentsDaoImpl.queryAll();
studentsList.forEach(System.out::println);
}
@Test
public void testUpdate() {
Students s = (Students) context.getBean("s1");
s.setMajor("葵花宝典");
try {
boolean flag = studentsDaoImpl.update(s);
Assert.isTrue(flag, "");
} catch (Exception ex) {
ex.printStackTrace();
}
}
@Test
public void testDelete() {
try {
boolean flag = studentsDaoImpl.delete("S0002");
Assert.isTrue(flag, "");
} catch (Exception ex) {
ex.printStackTrace();
}
}
@Test
public void testAddBatch() {
try {
List<Students> studentsList = (List<Students>) context.getBean("studentList");
studentsDaoImpl.addBatch(studentsList);
} catch (Exception ex) {
ex.printStackTrace();
}
}
@After
public void destroyResource(){
}
}
@ContextConfiguration 加载 SpringConfiguration.class的方式。
需要在SpringConfiguration.java中添加 jdbcTemplate的bean.
//SpringConfiguration.java
@Bean("jdbcTemplate")
public JdbcTemplate initJdbcTemplate() {
JdbcTemplate jdbcTemplate = null;
ComboPooledDataSource dataSource = null;
try {
jdbcTemplate = new JdbcTemplate();
dataSource = new ComboPooledDataSource();
Properties properties = new Properties();
properties.load(MySpringConfiguration.class.getClassLoader().getResourceAsStream("jdbc.properties"));
dataSource.setUser(properties.getProperty("jdbc.user"));
dataSource.setPassword(properties.getProperty("jdbc.password"));
dataSource.setDriverClass(properties.getProperty("jdbc.driverClass"));
dataSource.setJdbcUrl(properties.getProperty("jdbc.jdbcUrl"));
dataSource.setInitialPoolSize(Integer.parseInt(properties.getProperty("initPoolSize")));
dataSource.setMaxPoolSize(Integer.parseInt(properties.getProperty("maxPoolSize")));
jdbcTemplate.setDataSource(dataSource);
return jdbcTemplate;
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
测试类如下:
import com.entity.Students;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.context.ApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.Assert;
import javax.annotation.Resource;
import java.util.List;
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {SpringConfiguration.class})
public class StudentDaoImplTest {
@Resource
private ApplicationContext context;
@Resource
private StudentsDao studentsDaoImpl;
@BeforeClass
public static void initStudentsTable() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
JdbcTemplate jdbcTemplate = (JdbcTemplate) context.getBean("jdbcTemplate");
String sql = "CREATE TABLE IF NOT EXISTS `students` (\n" +
" `sid` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,\n" +
" `sname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,\n" +
" `gender` varchar(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,\n" +
" `major` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,\n" +
" PRIMARY KEY (`sid`) USING BTREE\n" +
") ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = Dynamic;";
jdbcTemplate.execute(sql);
}
@Test
public void testAdd() {
try {
Students s = (Students) context.getBean("s1");
boolean flag = studentsDaoImpl.add(s);
Assert.isTrue(flag, "");
} catch (Exception ex) {
ex.printStackTrace();
}
}
@Test
public void testQueryById() {
Students s = studentsDaoImpl.query("S0001");
System.out.println(s);
}
@Test
public void testQueryAll() {
List<Students> studentsList = studentsDaoImpl.queryAll();
studentsList.forEach(System.out::println);
}
@Test
public void testUpdate() {
Students s = (Students) context.getBean("s1");
s.setMajor("葵花宝典");
try {
boolean flag = studentsDaoImpl.update(s);
Assert.isTrue(flag, "");
} catch (Exception ex) {
ex.printStackTrace();
}
}
@Test
public void testDelete() {
try {
boolean flag = studentsDaoImpl.delete("S0002");
Assert.isTrue(flag, "");
} catch (Exception ex) {
ex.printStackTrace();
}
}
@Test
public void testAddBatch() {
try {
List<Students> studentsList = (List<Students>) context.getBean("studentList");
studentsDaoImpl.addBatch(studentsList);
} catch (Exception ex) {
ex.printStackTrace();
}
}
@After
public void destroyResource(){
}
}