Java Junit单元测试


前言

所谓单元测试,就是针对最小的功能单元,编写测试代码对其进行正确性测试。


一、Junit单元测试—普通Java文件

对于普通Java文件的单元测试,由于未使用Maven进行依赖管理,我们需要手动导入依赖文件,这里首先介绍一下IDEA中如何导入依赖。

1. Idea依赖导入方式

  1. 在模块下创建lib文件夹
  2. 将需要导入的依赖复制到lib文件夹下
  3. 点击lib文件夹,右键选择Add as Library
    在这里插入图片描述
  4. 选择模块创建(根据实际需求选择即可)
    在这里插入图片描述

2. Junit的使用

在导入Junit依赖后,我们就可以使用Junit提供的工具进行测试
在这里插入图片描述

示例

被测试代码

package day14.MyJunit;

public class MathUtils {
    public static int getSum(int a, int b) {
        return a + b;
    }
    public static int subtract(int a, int b) {
        return a - b;
    }
    public static int multiply(int a, int b) {
        return a * b;
    }
    public static int divide(int a, int b) {
        return a / b;
    }
}

junit测试代码的实现

package day14.MyJunit;

import org.junit.Test;

//第一步: 创建测试类, 测试类的类名一般是:   被测试类类名 + Test
public class MathUtilsTest {
    /*
        第二步: 为了保证每个方法独立, 为测试的每个方法单独创建测试方法
        测试方法要求(规格):
            (1) 不能有参数
            (2) 不能返回值
            (3) 方法名建议:  test+被测试的方法(遵循驼峰命名规范)
            (4) 修饰符必须是public
     */

    // 第三步: 为了保证每个测试方法都能够独立运行,需要加上一个注解@Test

    /*
     @Test : 可以让测试方法独立运行  (核心注解)
     @Before(@BeforeEach): 在每个测试方法运行之前都运行一次
     @After(@AfterEach): 在每个测试方法运行之后都运行一次
     @BeforeClass(@BeforeAll): 在类加载的时候走一次(该注解修饰的测试方法必须是静态方法)
     @AfterClass(@AfterAll) : 在所有的测试方法走完之后走一次(同样只能修饰静态方法 就是静态代码块)

     总结:
        使用步骤:
            (1) 导包
            (2) 创建测试类:
                    类名要求: 要测试的类+Test
            (3) 在测试类中定义测试方法
                    方法要求:
                        (1) 没有返回值, 没有参数
                        (2) 权限修饰符必须是public
                        (3) 方法名要求:test+要被测试的方法名
            (4) 抗上@Test即可
    优点:
        (1) 每个方法测试都单独测试互不影响
        (2) 自动化测试
        (3) 能够生成测试报告
        (4) 还可以断言Assert
 */
/*
    断言:所谓断言:意思是程序员可以预测程序的运行结果,检查程序的运行结果是否与预期一致。
    由junit的Asset工具类实现
        eg: Assset.assrtEquals("提示消息",预期目标,实际结果);
*/

    @BeforeClass
    public static void beforeOne(){
        System.out.println("我只走一次");
    }
    @AfterClass
    public static void afterOne(){
        System.out.println("我只走一次");
    }
    @Test
    public void textGetsum(){
        System.out.println(MathUtils.getSum(10086, 10010));
    }
    @Test
    public void testSubtract(){
        System.out.println(MathUtils.subtract(10086, 10010));
    }
    @Test
    public void testMultiply(){
        System.out.println(MathUtils.multiply(10086, 10010));
    }
    @Test
    public void testDivide(){
        System.out.println(MathUtils.divide(10086, 10010));
    }
    @Before
    public void before(){
        System.out.println("加载资源");
    }
    @After
    public void afer(){
        System.out.println("释放资源");
    }


    @Test
    public void textGetSum(){
        int sum = MathUtils.getSum(10, 20);
        Assert.assertEquals("提示消息",40,sum);
    }
}

Asset类方法展示

在这里插入图片描述

上述断言测试结果
在这里插入图片描述

二、Junit单元测试—Maven

在这里插入图片描述

  1. 在pom.xml中,引入JUnit的依赖。
<!--Junit单元测试依赖-->
<dependency>
  <groupId>org.junit.jupiter</groupId>
  <artifactId>junit-jupiter</artifactId>
  <version>5.9.1</version>
  <scope>test</scope>
</dependency>
  1. 在test/java目录下,创建测试类,并编写对应的测试方法,并在方法上声明@Test注解。

1. 普通测试

被测试类

package org.example;

public class UserService {
    //身份证号---多少岁
    //412821200109114459
    public int getAge(String card){
        return (2024 - Integer.parseInt(card.substring(6, 10)));
    }
}

测试类1

import org.example.UserService;
import org.junit.jupiter.api.*;
import org.junit.jupiter.api.Test;


public class UserServiceTest {

    @Test
    public void testGetAge(){
        int age = new UserService().getAge("412821200109114459");
        System.out.println(age);
        Assertions.assertEquals(23,age,"结果有误");
    }
    @BeforeEach
    public void beforeEach(){
        System.out.println("每个方法执行之前,都先执行我");
    }
    @BeforeAll
    public static void beforeAll(){
        System.out.println("我在类加载的时候加载一次");
    }
    @AfterEach
    public void afterEach(){
        System.out.println("每个方法执行执行之后,我都要执行");
    }
    @AfterAll
    public static void afterAll(){
        System.out.println("我在所以方法执行结束时执行一次");
    }
}

在这里插入图片描述

2. 单参数测试

@DisplayName注解和(@ParameterizedTest,@ValueSource注解)

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

//设置执测试类名  默认为类名
@DisplayName("测试-学生业务")
public class UserServiceTest {

    //设置测试方法名 默认为方法名
    @DisplayName("测试-学生年龄")
    @Test
    public void testGetAge(){
        int age = new UserService().getAge("412821200109114459");
        System.out.println(age);
        Assertions.assertEquals(23,age,"结果有误");
    }

    @DisplayName("多参数测试-学生年龄")
    //标志,代表有参数测试
    @ParameterizedTest
    //设置测试参数  方法测试方法会依次遍历注解数组中的元素
    @ValueSource(strings={"412821196245632147","412821196214141118","145987196212354415"})
    public void testGetAges(String s){
        int age = new UserService().getAge(s);
        //断言
        Assertions.assertEquals(62,age,"戳");
    }
}

测试结果

在这里插入图片描述

@ValueSoure注解源码

在这里插入图片描述

3. 多参数测试

@CsvSource注解

 /*
    @CsvSource 是一个在 JUnit 5 中用于提供测试数据的注解,特别是在参数化测试中非常有用。它允许你以逗号分隔值(CSV)
    格式直接在测试类中定义测试数据,并且这些数据会被自动注入到测试方法中。

    基本用法
    @CsvSource 注解可以被用在 @ParameterizedTest 上,来为测试方法提供一组或多组参数。每组参数都是一行CSV格式的数据,
    其中每个值由逗号分隔。
*/
    @ParameterizedTest
    @CsvSource({"lvbu,123456", "xiaoqiao,123456"})  //每个字符串数组的元素都是一组数据     
    public void testQuery(String username , String password) { //方法参数与每组数据对应,方法会依次测试每组数据
        //方法体
    }

/*
    CSV 文件的基本结构
        分隔符:最常用的分隔符是逗号(,),但也可以使用其他字符,比如制表符(\t)、竖线(|)等。
        行:每行代表一条记录或一行数据。
        列:每列代表一个特定的属性或字段。
    CSV 文件的例子
        Alice,22,New York
        Bob,25,Los Angeles
*/

@CsvFileSource注解 读取CSV文件中数据

import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvFileSource;
import org.junit.jupiter.params.provider.CsvSource;

import java.sql.*;

public class JDBCDQLTest {
    @Test
    @ParameterizedTest
    @CsvFileSource(resources = "jdbctest.csv")  //该注解可以读取csv文件中内容,每一行为一组
    public void testDqlJDBC(String _name,String _password) throws ClassNotFoundException, SQLException {
        //链接数据库
        Class.forName("com.mysql.cj.jdbc.Driver");
        String url = "JDBC:mysql://localhost:3306/itheima";
        Connection connection = DriverManager.getConnection(url, "root", "root");

        //获取数据库执行对象
        Statement statement = connection.createStatement();

        //执行SQL语句
        ResultSet resultSet = statement.executeQuery("select * from user where username ='"+ _name+"'and password = '"+_password+"'");

        //读取结果中的语句
        while (resultSet.next()){
            int id = resultSet.getInt("id");
            String username = resultSet.getString("username");
            String name = resultSet.getString("name");
            int age = resultSet.getInt("age");
            System.out.println("id:"+id+"  username:"+username+"  name:"+name+"  age:"+age);
        }

        //关闭资源
        connection.close();
        statement.close();

    }
}

在这里插入图片描述

三、Junit单元测试—SpringBoot项目

在SpringBoot项目中,如果只是进行简单的单元测试,这直接按照上述Maven操作即可,但如果测试需要获取项目上下文内容(也就是Bean),则需要创建与主配置类结构一致的测试类,并加上引入@SpringBootTest

1. 使用步骤

  1. 引入Maven依赖
   <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
   </dependency>
  1. 创建测试类
    在这里插入图片描述
  2. 引入@SpringBootTest注解
    在这里插入图片描述
  3. 进行测试操作,使用注解进行测试即可

2. @SpringBootTest详解

  • @SpringBootTest 是 Spring Boot 提供的一个注解,用于启动一个完整的 Spring Boot 应用程序上下文,并在其中执行测试。这个注解通常用于集成测试,因为它可以模拟完整的应用程序环境,包括配置文件、自动装配的 Bean、以及依赖项等。
  • @SpringBootTest 注解可以被应用在一个测试类上,它会启动一个完整的 Spring Boot 应用程序上下文,并加载所有的 Bean。(扫描相同包结构下对应的主配置类,或者classes指定的住配置类,SpringBoot项目中导入spring-boot-startr-test后测试类和包结构会自动生产,该注解包含了junit单元测试注解,所以实际上用的还是junit)

示例

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class ApplicationContextTest {

    @Autowired
    private SomeService someService;

    @Test
    public void contextLoads() {
        // 这里可以验证应用程序上下文是否正确加载
        // 例如,验证某些 Bean 是否正确初始化
        assert someService != null;
    }
}
/*
在这个例子中:
● @SpringBootTest 注解启动了一个完整的 Spring Boot 应用程序上下文。
● @Autowired 注入了一个 SomeService Bean,用于测试。

*/
  • 配置选项
    • @SpringBootTest 注解还提供了一些可选的配置选项,用于控制应用程序上下文的加载方式:
      • webEnvironment:指定是否启动 Web 环境。可以选择 WebEnvironment.RANDOM_PORT、WebEnvironment.DEFINED_PORT 或 WebEnvironment.NONE。
      • classes:指定要加载的主配置类(就是引导类,启动类)。
      • properties:指定要在测试期间覆盖的属性。

示例 通过classes指定后,这不必须与主配置类结构一致

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
                classes = Application.class,
                properties = {"server.port=0", "spring.datasource.url=jdbc:h2:mem:testdb"})
public class ApplicationContextTest {

    @Autowired
    private SomeService someService;

    @Test
    public void contextLoads() {
        // 这里可以验证应用程序上下文是否正确加载
        // 例如,验证某些 Bean 是否正确初始化
        assert someService != null;
    }
}
/*
● webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT 
    表示启动一个随机端口的 Web 环境。
● classes = Application.class 指定主配置类。
● properties 用于覆盖配置文件中的属性。

*/
  • 使用 @RunWith(SpringRunner.class)
    在 JUnit 4 中,你需要使用 @RunWith(SpringRunner.class) 来启动 Spring Boot 应用程序上下文。但在 JUnit 5 中,Spring Boot 已经默认使用了 SpringRunner,因此不再需要显式声明。
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationContextTest {

    @Autowired
    private SomeService someService;

    @Test
    public void contextLoads() {
        // 这里可以验证应用程序上下文是否正确加载
        // 例如,验证某些 Bean 是否正确初始化
        assert someService != null;
    }
}
  • 34
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值