【Java】[junit] (一)Java 测试入门 ,junit的基本操作 ,@Test等注解的用法

Java Testing

本文带你入门junit和mockito。

junit

环境和前置知识

这里我用的是IDEA 、jdk11

需要以下基础:

  • java (类、静态函数)
  • maven (知道怎么用pom.xml添加依赖)
  • IDEA(基础操作)

新建一个项目

在这里插入图片描述

导入maven依赖

打开pom.xml 添加junit的几行依赖内容。
在这里插入图片描述


   <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>RELEASE</version>
            <scope>test</scope>
        </dependency>

代码结构

在这里插入图片描述

现在的idea都会自动生成标准的项目结构,main文件夹里的java文件夹放程序文件,test内的java文件夹则明显就是存放我们测试代码的地方。
通常,单元测试是在单独的源文件夹中创建的,以使测试代码与真实代码分开。Maven 和 Gradle 构建工具的标准约定是:

  • src/main/java - 用于 Java 类
  • src/test/java - 用于测试类

编写一个待测试的demo

我们写个简单的计算器,模拟实际开发中的一些常见的开发问题,并进行测试。
在这里插入图片描述

我们编写了如下代码:

/**
 * @author gongfpp  https://github.com/gongfpp
 * @date 2022/8/26 9:44
 */
public class Calculator {
    
    

    private int value;

    public static int add(int a,int b){
    
    
        return a+b;
    }

    public static int sub(int a,int b){
    
    
        return a+b;
    }

    public static void main(String[] args) {
    
    
        System.out.println("yes");
    }

}


在这里,我开发代码时复制黏贴不小心把减法(sub)的代码ctrl +v 粘了个加法的进去(假装),但是由于只是一个符号的区别,我没有看出来(假装我是瞎子,但实际开发中代码复杂的时候确实非常难看出来,有时候浪费一天结果发现是很低级的错误,有经历过的都懂)
,接下来我们进行测试

编写测试代码

我们很容易想到在main函数里调用编写的代码进行测试,但程序并非一成不变的,如果每次加新功能测试的时候,main函数内每次都注释掉原有的代码而添加测试代码,测完了再删测试代码并还原注释,一是非常麻烦,二是非常臃肿,三是不规范。于是我们需要一些测试框架来辅助我们进行单元测试,单元测试指的是能对能测试的最小单元(unit)进行测试,一般是一个方法。
在这里插入图片描述

我们在test/java/内新建一个CalculatorTest类
Import我们需要的test注解,并写一个没有任何执行内容的方法,在它上面添加@Test注解。

/**
 * @author gongfpp  https://github.com/gongfpp
 * @date 2022/8/26 9:55
 */
import org.junit.jupiter.api.Test;
public class CalculatorTest {
    
    
    @Test
    public void test(){
    
    

    }
}

这时这个方法可以被作为独立单元来进行测试,左边能看到绿色的运行。这样我们免去了每次都运行main方法的繁杂,而且每个@Test方法都能独立运行。
运行结果如下:
在这里插入图片描述

这里由于什么都没写,便只会有测试通过的结果。
太棒了,不写测试代码就不会通不过测试!(别)

为了更多的测试功能,我们import一些静态函数。

import static org.junit.jupiter.api.Assertions.*;

import static 的意思是导入后面的包内的类的静态函数,这样我们使用的时候就不需要类名。
不然我们调用的时候需要Assertions.assertEquals(); 这样比较长,也没必要,测试类里一般只有测试方法,没有重名的风险。

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class CalculatorTest {
    
    
    @Test
    public void add5_5_10(){
    
    
        assertEquals(10,Calculator.add(5,5));
    }
    
    @Test
    public void sub10_5_5(){
    
    
        assertEquals(5,Calculator.sub(10,5));
    }
}


函数名建议使用一眼能看出来的含义,这里我们测试两个用例(case),assertEquals()的参数分别为期望值和实际值,当两个相同则测试通过,不同则失败。
在这里插入图片描述

我们点击类旁的run则可以运行所有带@Test的测试用例。运行结果如下。
在这里插入图片描述

明确指出期望值和实际值,这样我们就能去修bug了。

同理,常用的测试函数如下 ,可以在注释里看函数作用:

/**
 * @author gongfpp  https://github.com/gongfpp
 * @date 2022/8/26 9:55
 */
import org.junit.jupiter.api.*;


import java.time.Duration;

import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assumptions.*;

public class CalculatorTest {
    
    
    @Test
    public void add5_5_10(){
    
    
        assertEquals(10,Calculator.add(5,5));
    }

    @Test
    public void sub10_5_5(){
    
    
        assertEquals(5,Calculator.sub(10,5));
    }


    @Test
    public void testTrueWithTrue(){
    
    
        //某个结果必须为true,否则测试失败 这里成功
        assertTrue(true);
    }

    @Test
    @DisplayName("我的名字会代替函数名出现在测试运行窗口,你跑我一下试试")
    public void tetsTrueWithFalse(){
    
    
        //某个结果必须为true,否则测试失败 这里失败
        assertTrue(false);
    }

    @Test
    public void testThrow(){
    
    
        //运行不抛出异常,这里一般用lambda函数,在lambda内写逻辑代码,lambda固定格式 ()->{} ,这里只需要知道代码写在大括号里就行了。
        assertDoesNotThrow(()->{
    
    
            throw new Exception("AAA");
        });
    }


    @Test
    public void testTimeout1Sec(){
    
    
//        限制时间未完成执行则测试不通过,第一个函数为Duration.ofxxx ,可选秒、分钟、小时等,
        assertTimeout(Duration.ofSeconds(1),()->{
    
    
            //线程休眠4秒,这里时间限制是1秒,所以肯定运行超时,测试不通过
            Thread.sleep(4000);
        });
    }

    @BeforeEach
    public void beforeEach(){
    
    
//        BeforeEach一般是每个方法前的初始化,比如Calculator calculator = new Calculator() 这样的代码,
//        每次都要写一遍很麻烦,所以有了这个,可以理解为这里的代码会被复制黏贴到每个test函数的开头部分,不能是static
        System.out.println("每个运行方法前我出来一次  我不能是静态函数");
    }

    @BeforeAll
    public static void beforeAll(){
    
    
//        beforeAll一般是所以方法执行前的一次操作,比如LogSave("开始测试calculor类"),这样的代码,一批测试只运行一次,
//        必须是static,可以理解为先执行这里的代码,再去分别运行其他的@Test代码
        System.out.println("执行所有测试前我来一次 我必须是静态函数");
    }


    //可以代替@Test 并且跑3次,参数为运行次数
    @RepeatedTest(3)
    public void other(){
    
    
//        当参数条件为true才往下运行,否则忽略该测试
//        比如先跑一个条件方法,当满足才往下继续
        assumeTrue(false);


    }
}

猜你喜欢

转载自blog.csdn.net/gongfpp/article/details/126540432