← 返回首页
Spring基础教程(十七)
发表时间:2020-05-17 14:46:19
讲解Junit单元测试

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(){

    }
}