junit单元测试代码

java怎么针对main函数进行单元测试:需要测试的代码如下
package Part1;

import java.util.Scanner;

public class LeapYear1 {

public static void main(String[] args) {
    Scanner input = new Scanner(System.in);
    String yearStr;
    int year;
    while (true) {
        System.out.print("请输入4位年份(输入q退出程序):");
        yearStr = input.nextLine();
        if (yearStr.equals("q")) {
            break;
        } else if (!yearStr.matches("\\d{4}")) {
           System.out.println("输入有误,请重新输入4位数字年份");
           continue;
        }
     year = Integer.parseInt(yearStr);
     if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
         System.out.println(year+"是闰年");
     } else {
         System.out.println(year+"不是闰年");
     }
   }
}    

}

main方法可以直接执行测试的,如果你非要调用 LeapYear1.main()方法测试,可以通过下面代码测试:
1 创建一个测试类,使用JUnit的@Test注解标记测试方法。

import org.junit.Test;
import java.io.ByteArrayInputStream;
import java.util.Scanner;

public class LeapYear1Test {

    @Test
    public void testLeapYear() {
        String input = "2020\nq\n"; // 模拟用户输入
        System.setIn(new ByteArrayInputStream(input.getBytes())); // 重定向标准输入流
        LeapYear1.main(new String[]{}); // 调用待测试的main函数
    }
}


2 在测试方法中,使用ByteArrayInputStream模拟用户输入,重定向标准输入流,然后调用待测试的main函数。

3 运行测试类,观察测试结果。

main方法就是java程序的主入口:直接右键选择运行,如图示:

img

或者单独拎出来一个单元测试方法:

img

  • 你可以参考下这个问题的回答, 看看是否对你有帮助, 链接: https://ask.csdn.net/questions/7415111
  • 我还给你找了一篇非常好的博客,你可以看看是否有帮助,链接:单元测试系列二-单元测试规范(适用于Java)
  • 除此之外, 这篇博客: Java单元测试知识总结(基于JUnit)中的 在日常开发中离不开进行代码的测试,因此很有必要学会如何进行规范的单元测试 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:

  • 单元测试的好处:

    1、提升软件质量

    2、促进代码优化

    3、提升研发效率

    4、增加重构自信


    单元测试基本原则:(AIR原则,必须用断言式来检测,符合BCDE原则)

    1、Automatic(自动化)

    2、Independent(独立性)

    3、Repeatable(可重复)

    4、Border,边界值测试,包含循环边界、特殊值、特殊值时间点、数据顺序

    5、Correct,正确的输入,并得到预期的结果

    6、Design,与设计文档像结合,来编写单元测试

    7、Error,单元测试用于证明程序是有错的,需要强制进行错误的输入,来检测是否能达到预期的结果。


    单元测试覆盖率

    粗粒度覆盖率:类覆盖和方法覆盖(只要类和参数和方法都调用和执行到了,就说这个类被测试覆盖了)

    细粒度覆盖率:

    1、行覆盖:是否每行都被执行到了。

    2、分支覆盖:是否每个分支都被覆盖到了

    3、条件覆盖:判定中是否每一个条件的所有可能情况至少被执行一次。注意一些&&和||的短路执行,要覆盖到。


    单元测试编写:

    工具:

    1、主流的为JUnit和TestNG(这里主要介绍JUnit)

    2、JUnit注解:

    @Test 注明这个方法是测试方法,JUnit在测试阶段能检测到使用该注解的方法,标明它们可以测试运行

    @TestFactory 注明一个方法是基于数据驱动的动态测试数据源

    @ParameterizedTest 注明是测试方法,可以让一个测试方法使用不同的入参运行多次

    @RepeatedTest 注明自定义运行次数

    @BeforeEach 指定每个测试方法运行前先执行该方法,一般用于数据准备

    @AfterEach 每个测试方法运行后都执行该方法,一般用于删除数据(组成测试回环,新增的数据,测试完后删除)

    @BeforeAll 每个测试类运行前,都运行一个指定方法

    @AfterAll 每个测试类运行后,都运行一个指定方法

    @Disabled 注明该测试方法不再运行

    @Nested 为测试添加嵌套层级,以便组织用例结构

    @Tag 为测试类或方法添加标签,以便有选择性的执行


    常用的断言式:

    1、fail()    断言测试失败

    2、assertTrue() /assertFalse()    断言条件为真或假

    3、assertNull() / assertNotNull()    断言条件为非空

    4、assertEquals() / assertNotEquals() 断言指定两个值相等或不相等,使用equals方法比较

    5、assertArrayEquals()    断言数组元素全部相等

    6、assertSame() / assertNotSame()    断言两个对象是否相等

    7、assertThrows() / assertDoesNotThrow()    断言是否抛出了一个特定类型的异常

    8、assertTimeout() / assertTimeoutPreemptively()    断言是否执行超时,区别在于测试程序是否在同一个线程内执行

    9、assertIterableEquals()    断言迭代器元素是否都相等

    10、assertLinesMatch()    断言字符串列表中全部元素都正则匹配

    11、assertAll()    断言多个条件同时满足

    还有一种AssertJ断言方式(流式断言),这种方式可以进行像Java8流式编程一样,进行流式的断言处理,大家可以自行搜素了解一下,当需要断言的条件有多个的时候,流式断言十分简便。


    测试实例代码(规范代码):

    需要被测试的类:

    
    /**
     * 需要被测试的类
     */
    public class TestClass {
        public String getName(){
            return "TestClass";
        }
    
        public int getInt(int i){
            return i;
        }
        public int getSum(int a, int b){
            return a+b;
        }
        public boolean getFalse(){
            return false;
        }
        public boolean getTrue(){
            return true;
        }
    }
    

    测试类:

    
    import org.junit.jupiter.api.*;
    import org.junit.jupiter.params.ParameterizedTest;
    import org.junit.jupiter.params.provider.CsvSource;
    
    import static org.junit.jupiter.api.Assertions.assertEquals;
    import static org.junit.jupiter.api.Assertions.assertTrue;
    
    @DisplayName("学习JUnit")
    public class TestJUnit {
        //定义待测试类的实例
        private TestClass testClass ;
    
        /**
         * 定义在整个测试类开始执行前的操作
         * 通过包括全局和外部资源的创建和初始化
         */
        @BeforeAll
        public static void init(){
    
        }
    
        /**
         * 定义在整个测试类执行完之后执行的操作
         * 通过包括全局和外部资源的释放和销毁(各种连接的注销,释放等)
         */
        @AfterAll
        public static void cleanup(){
    
        }
    
        /**
         * 在每个测试用例开始前执行的操作
         * 通过包括基础数据和运行环境的准备(给数据库添加数据测试等等)
         */
        @BeforeEach
        public void create(){
    
            this.testClass = new TestClass();
        }
    
        /**
         * 在每个测试用例完成后执行的操作
         * 通常包括运行环境的清理
         */
        @AfterEach
        public void destory(){
    
        }
    
        /**
         * 测试用例,测试类的求和功能
         */
        @Test
        @DisplayName("测试求和功能")
        public void getSum(){
            int a = 1;
            int b = 2;
            int c = testClass.getSum(a,b);
            assertEquals(3,c);
        }
    
        /**
         * 输入多组参数,重复测试
         * @param a
         * @param b
         * @param ans
         */
        @ParameterizedTest
        @DisplayName("测试重复求和功能")
        @CsvSource({
                "1, 2, 3",
                "1, 3, 3"
        })
        public void getSums(int a, int b, int ans){
            int c = testClass.getSum(a,b);
            assertEquals(ans,c);
        }
    
        /**
         * 禁用该测试用例,该测试用例不会被执行
         * 会出现在最终的报告中
         */
        @Disabled
        @Test
        @DisplayName("测试类名是否正确")
        public void getName(){
            assertTrue("TestClass".equals(testClass.getName()));
        }
    
        @Nested
        @DisplayName("表示属于TestJunit测试的子级测试(如:交易服务测试下的用户交易测试,一般建议不超过三层)")
        class NestTest{
    
            @DisplayName("嵌套测试")
            public void nestTest(){
                assertTrue(true);
            }
        }
    
        /**
         * 标注运行频率,
         * 可以使用maven添加插件,先执行所有为fast的,后执行slow的测试用例
         */
        @Test
        @Tag("fast")  //slow
        @DisplayName("返回True")
        public void getTrue(){
            assertTrue(testClass.getTrue());
        }
    
    }

     

  • 您还可以看一下 赵庆元老师的全栈工程师手把手带你学Java语言课程中的 main方法里面的数组小节, 巩固相关知识点