Java单元测试、Junit、断言、单元测试常见注解、单元测试Maven依赖范围、Maven常见问题解决方法

一. 测试

  1. 测试:是一种用来促进鉴定软件的正确性、完整性、安全性和质量的过程

  2. 阶段划分:单元测试、集成测试、系统测试、验收测试。

① 单元测试:对软件的基本组成单位进行测试,最小测试单位;目的检验软件基本组成单位的正确性,测试人员:开发人员

② 集成测试:将已分别通过测试的单元,按设计要求组合成系统或子系统,在进行的测试;目的检验单元之间的协作是否正确;测试人员:开发人员

③ 系统测试:对已经集成好的软件进行彻底的测试;目的验证软件系统的正确性、性能是否满足指定的要求;测试人员:测试人员

④ 验收测试(交付测试):是针对用户需求、业务流程进行的正式的测试;目的验证软件系统是否满足验收标准;测试人员:客户/需求方

  1. 测试方法:白盒测试、黑盒测试 及 灰盒测试

① 白盒测试:清楚软件内部结构、代码逻辑;用于验证代码、逻辑的正确性;

② 黑盒测试:不清楚软件内部结构、代码逻辑;用于验证软件的功能、兼容性等;

③ 灰盒测试:结合了白盒和黑盒的特点,既关注软件的内部结构又考虑外部功能

二. 单元测试快速入门

  1. 单元测试:就是针对最小的功能单元(方法),编写测试代码对其正确性进行测试

  2. JUnit:最流行的Java测试框架之一,提供了一些功能,方便程序进行单元测试(第三方公司)

  3. main方法测试存在的问题:测试代码与源代码未分开,难维护;一个方法测试失败,影响后面方法;无法自动化测试,得到测试报告;

  4. JUnit单元测试:测试代码与源代码分开,便于维护;可根据需要进行自动化测试;可自动分析测试结果,产出测试报告

三. 使用JUnit

  1. 在pom.xml中,引入Junit的依赖

  2. 在test/Java目录下,创建测试类,并编写对应的测试方法,并在方法上声明@Test注解

注意:JUnit单元测试类命名规范为:XxxxTest【规范】;Junit单元测试的方法,必须声明为 public void【规定】

  1. 运行单元测试(测试通过:绿色;测试失败:红色)
java 复制代码
package org.example;

import java.time.LocalDate;
import java.time.Period;
import java.time.format.DateTimeFormatter;

public class UserService {

    /**
     * 给定一个身份证号, 计算出该用户的年龄
     * @param idCard 身份证号
     */
    public Integer getAge(String idCard){
        if (idCard == null || idCard.length() != 18) {
            throw new IllegalArgumentException("无效的身份证号码");
        }
        String birthday = idCard.substring(6, 14);
        LocalDate parse = LocalDate.parse(birthday, DateTimeFormatter.ofPattern("yyyyMMdd"));
        return Period.between(parse, LocalDate.now()).getYears();
    }

    /**
     * 给定一个身份证号, 计算出该用户的性别
     * @param idCard 身份证号
     */
    public String getGender(String idCard){
        if (idCard == null || idCard.length() != 18) {
            throw new IllegalArgumentException("无效的身份证号码");
        }
        return Integer.parseInt(idCard.substring(16,17)) % 2 == 1 ? "男" : "女";
    }

}
java 复制代码
/*
* 测试类
* */
public class UserServiceTest {

    @Test
    public void testGetAge(){
        UserService userService = new UserService();
        Integer age = userService.getAge("112223199701011234");
        System.out.println(age);

    }

}

四. 单元测试-断言

单元测试运行不报错(绿色),并不代表代码没问题,测试通过;

JUnit提供了一些辅助方法,用来帮助我们确定被测试的方法是否安装预期的效果正常工作,这种方式称为断言

|----------------------------------------------------------------------|---------------------------|
| 断言方法 | 说明 |
| Assertions.assertEquals(object exp, Object act, String msg) | 检查两个值是否相等,不相等就报错。 |
| Assertions.assertNotEquals(object unexp, Object act, String msg) | 检查两个值是否不相等,相等就报错。 |
| Assertions.assertNull(object act, String msg) | 检查对象是否为null,不为null,就报错。 |
| Assertions.assertNotNull(object act, String msg) | 检查对象是否不为null,为null,就报错。 |
| Assertions.assertTrue(boolean condition, String msg) | 检查条件是否为true,不为true,就报错。 |
| Assertions.assertFalse(boolean condition, String msg) | 检查条件是否为false,不为false,就报错。 |
| Assertions. assertThrows(class expType, Executable exec, String msg) | 检查两个对象引用是否相等,不相等,就报错 |

上述方法形参中的最后一个参数msg,表示错误提示信息,可以不指定(有对应的重载方法)

java 复制代码
package org.example;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

/*
* 测试类
* */
public class UserServiceTest {

    @Test
    public void testGetAge(){
        UserService userService = new UserService();
        Integer age = userService.getAge("112223199701011234");
        System.out.println(age);

    }

    @Test
    public void testGetGender(){
        UserService userService = new UserService();
        String gender = userService.getGender("112223199701011234");
        System.out.println(gender);
    }

    /*
    * 断言
    * */
    @Test
    public void testGenderWithAssert(){
        UserService userService = new UserService();
        String gender = userService.getGender("112223199701011234");
        System.out.println(gender);
        //断言机制
        Assertions.assertEquals("女",gender,"性别获取异常");
    }

    /*
     * 断言2
     * */
    @Test
    public void testGenderWithAssert2(){
        UserService userService = new UserService();
        //断言
        Assertions.assertThrows(NullPointerException.class, ()->{//预期抛出的异常IllegalArgumentException
            userService.getGender(null);
        });
    }

}

五. 单元测试-常见注解

Junit中还提供了一些注解,增强其功能,常见的注解有:

|--------------------|----------------------------------|--------------------|
| 注解 | 说明 | 备注 |
| @Test | 测试类中的方法用它修饰才能成为测试方法,才能启动执行 | 单元测试 |
| @ParameterizedTest | 参数化测试的注解(可以让单个测试运行多次,每次运行时仅参数不同) | 用了该注解,就不需要@Test注解了 |
| @Valuesource | 参数化测试的参数来源,赋予测试方法参数 | 与参数化测试注解配合使用 |
| @DisplayName | 指定测试类、测试方法显示的名称(默认为类名、方法名) | |
| @BeforeEach | 用来修饰一个实例方法,该方法会在每一个测试方法执行之前执行一次。 | 初始化资源(准备工作) |
| @AfterEach | 用来修饰一个实例方法,该方法会在每一个测试方法执行之后执行一次。 | 释放资源(清理工作) |
| @BeforeAll | 用来修饰一个静态方法,该方法会在所有测试方法之前只执行一次。 | 初始化资源(准备工作) |
| @AfterAll | 用来修饰一个静态方法,该方法会在所有测试方法之后只执行一次。 | 释放资源(清理工作) |

java 复制代码
package org.example;

import org.junit.jupiter.api.*;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

/*
* 测试类
* */
@DisplayName("测试用户信息测试类")
public class UserServiceTest {

    @BeforeAll //该方法会在所有测试方法之前只执行一次。
    public static void beforeAll(){
        System.out.println("Before All");
    }

    @AfterAll //该方法会在所有测试方法之后只执行一次。
    public static void afterAll(){
        System.out.println("After All");
    }

    @BeforeEach //该方法会在每一个测试方法执行之前执行一次。
    public  void beforeEach(){
        System.out.println("Before Each");
    }

    @AfterEach //该方法会在每一个测试方法执行之后执行一次。
    public void afterEach(){
        System.out.println("after All");
    }


    @Test
    public void testGetAge(){
        UserService userService = new UserService();
        Integer age = userService.getAge("112223199701011234");
        System.out.println(age);

    }

    @Test
    public void testGetGender(){
        UserService userService = new UserService();
        String gender = userService.getGender("112223199701011234");
        System.out.println(gender);
    }

    /*
    * 断言
    * */
    @Test
    public void testGenderWithAssert(){
        UserService userService = new UserService();
        String gender = userService.getGender("112223199701011234");
        System.out.println(gender);
        //断言机制
        Assertions.assertEquals("女",gender,"性别获取异常");
    }

    /*
     * 断言2
     * */
    @Test
    public void testGenderWithAssert2(){
        UserService userService = new UserService();
        //断言
        Assertions.assertThrows(NullPointerException.class, ()->{//预期抛出的异常IllegalArgumentException
            userService.getGender(null);
        });
    }

    /*
    * 参数化测试
    * */
    @DisplayName("测试用户性别")
    @ParameterizedTest
    @ValueSource(strings = {"112223199701011234", "112223199801011254", "112223199901011274"})
    public void testGetGender2(String idCards){
        UserService userService = new UserService();
        String gender = userService.getGender(idCards);
       //断言
        Assertions.assertEquals("男", gender);
    }


}

六.单元测试-企业开发规范

  1. 原则:编写测试方法时,要尽可能的覆盖业务方法中所有可能得情况(尤其是边界值)
java 复制代码
package org.example;

import org.junit.jupiter.api.*;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

/*
* 测试类
* */
@DisplayName("测试用户信息测试类2")
public class UserServiceTest2 {
    private UserService userService;

    @BeforeEach
    public void setUserService() {
        userService = new UserService();
    }

    /*
    * 测试获取性别 -null
    * */
    @Test
    @DisplayName("获取性别-null值")
    public void testGender1(){
       Assertions.assertThrows(IllegalArgumentException.class, () -> {
          userService.getGender(null);
       });
    }

    /*
     * 测试获取性别 -" "
     * */
    @Test
    @DisplayName("获取性别-空字符串")
    public void testGender2(){
        Assertions.assertThrows(IllegalArgumentException.class, () -> {
            userService.getGender("");
        });
    }

    /*
     * 测试获取性别 -字符长度不够18位
     * */
    @Test
    @DisplayName("获取性别-字符长度不够18位")
    public void testGender3(){
        Assertions.assertThrows(IllegalArgumentException.class, () -> {
            userService.getGender("123654");
        });
    }

    /*
     * 测试获取性别 -字符长度超过18位
     * */
    @Test
    @DisplayName("获取性别-字符长度超过18位")
    public void testGender4(){
        Assertions.assertThrows(IllegalArgumentException.class, () -> {
            userService.getGender("12345678901234567893");
        });
    }

    /*
     * 测试获取性别 -正常男
     * */
    @Test
    @DisplayName("获取性别-正常男")
    public void testGender5(){
        String gender = userService.getGender("130001199712211234");
        Assertions.assertEquals("男", gender);
    }

    /*
     * 测试获取性别 -正常女
     * */
    @Test
    @DisplayName("获取性别-正常女")
    public void testGender6(){
        String gender = userService.getGender("130001199712211224");
        Assertions.assertEquals("女", gender);
    }


}
  1. 测试覆盖率

七. 基于AI自动生成单元测试

  1. 安装插件

上述方式下载巨慢,建议官网下载后导入

下载安装-通义灵码

八. 单元测试-Maven依赖范围

  1. 在Maven项目中,test目录存放单元测试的代码,可以在main目录中编写单元测试,但是不规范
  1. 依赖的jar包,默认情况下,可以在任何地方使用,可以通过<scope>...</scope>设置其作用范围

作用范围:主程序范围有效;(main文件夹范围内)

测试程序范围有效;(test文件夹范围内)

是否参与打包运行;(pagekage指令范围内)

|-------------|-----|------|----|-------------|
| scope值 | 主程序 | 测试程序 | 打包 | 范例 |
| compile(默认) | Y | Y | Y | log4j |
| test | - | Y | - | JUnit |
| provided | Y | Y | - | servlet-api |
| runtime | - | Y | Y | JDBC驱动 |

XML 复制代码
         <!--Junit依赖        -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>5.9.1</version>
            <scope>test</scope>
        </dependency>

九. Maven常见问题解决方法

然后重新加载Maven

相关推荐
Java个体户10 分钟前
非maven地址方式引入jar
maven
PHASELESS41112 分钟前
Java排序算法百科全书:原理、实现与实战指南
java·数据结构·算法·排序算法
大胆刁民13 分钟前
java 代理
java·后端
AronTing16 分钟前
命令模式:从撤销操作到分布式调度的命令封装实践
java·后端·架构
liwulin050620 分钟前
【JAVA】在idea新加artifact时,点击Build-Build Artifacts时,新加的artifact不能选中
java·pycharm·intellij-idea
okok__TXF20 分钟前
Spring分析-IOC
java·后端·spring
老码识土24 分钟前
Kotlin 协程源代码泛读:suspend 函数
java
顾林海25 分钟前
深度解析ConcurrentHashMap工作原理
android·java·面试
ShiinaMashirol38 分钟前
代码随想录刷题|Day20(组合总数,组合总数2、分割回文串)
java·算法