当前位置: 首页 > article >正文

Java中的单元测试与JUnit

1.什么是单元测试?

单元测试是测试代码的最小单元,通常针对单个类或方法。单元测试旨在验证代码是否按预期运行,帮助发现潜在的逻辑错误和bug。一个好的单元测试应该具备以下特点:

  1. 独立性:每个测试应该独立执行,互不依赖。
  2. 快速性:单元测试应该快速运行,以便能够频繁地执行。
  3. 可重复性:测试结果应该稳定且可重复。

2.什么是JUnit?

JUnit是Java语言中的一个开源测试框架,能够帮助开发者编写可维护、可执行的测试代码。JUnit使得开发者可以方便地组织和执行测试,并生成详细的测试报告。

2.1JUnit的特点

  • 简单易用:使用注解来标识测试方法和生命周期方法。
  • 自动化测试:可以轻松集成到自动化构建工具中,如Maven、Gradle等。
  • 丰富的断言功能:JUnit提供了一系列断言方法来验证测试结果是否符合预期。

3.如何使用JUnit编写测试?

要使用JUnit,首先需要将其依赖添加到项目中。对于Maven项目,可以在pom.xml中添加以下依赖:

<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13.2</version>
        <scope>test</scope>
    </dependency>
</dependencies>

3.1编写第一个JUnit测试

被测试类 Calculator.java:

public class Calculator {
    public int add(int a, int b) {
        return a + b;
    }
    
    public int subtract(int a, int b) {
        return a - b;
    }
}

测试类 CalculatorTest.java:

import org.junit.Test;
import static org.junit.Assert.assertEquals;

public class CalculatorTest {
    
    @Test
    public void testAdd() {
        Calculator calculator = new Calculator();
        int result = calculator.add(2, 3);
        assertEquals(5, result);  // 断言结果应该为5
    }

    @Test
    public void testSubtract() {
        Calculator calculator = new Calculator();
        int result = calculator.subtract(5, 3);
        assertEquals(2, result);  // 断言结果应该为2
    }
}

在这个例子中,我们使用了两个测试方法testAdd()和testSubtract(),它们分别测试了add()和subtract()方法的正确性。使用@Test注解标记测试方法,assertEquals()方法用来检查实际结果是否与期望结果一致。

3.2常用的JUnit注解

  • @Test:标记一个方法为测试方法。
  • @Before:在每个测试方法之前执行,用于初始化一些准备工作。
  • @After:在每个测试方法之后执行,用于清理资源。
  • @BeforeClass:在所有测试方法运行之前执行,仅执行一次。
  • @AfterClass:在所有测试方法运行之后执行,仅执行一次。 @Ignore:忽略指定的测试方法。

例如:

import org.junit.*;

public class JUnitExample {

    // 在所有测试方法之前执行,仅执行一次
    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
        System.out.println("执行 @BeforeClass:全局初始化...");
    }

    // 在所有测试方法之后执行,仅执行一次
    @AfterClass
    public static void tearDownAfterClass() throws Exception {
        System.out.println("执行 @AfterClass:全局清理...");
    }

    // 在每个测试方法之前执行
    @Before
    public void setUp() throws Exception {
        System.out.println("执行 @Before:测试方法前的初始化...");
    }

    // 在每个测试方法之后执行
    @After
    public void tearDown() throws Exception {
        System.out.println("执行 @After:测试方法后的清理...");
    }

    // 标记为测试方法
    @Test
    public void testMethod1() {
        System.out.println("执行 @Test:测试方法1");
        Assert.assertEquals(1, 1);
    }

    // 标记为测试方法
    @Test
    public void testMethod2() {
        System.out.println("执行 @Test:测试方法2");
        Assert.assertTrue(true);
    }

    // 忽略此测试方法
    @Ignore("此测试方法被忽略")
    @Test
    public void ignoredTestMethod() {
        System.out.println("此测试方法应该不会被执行");
    }
}

输出:

执行 @BeforeClass:全局初始化...
执行 @Before:测试方法前的初始化...
执行 @Test:测试方法1
执行 @After:测试方法后的清理...
执行 @Before:测试方法前的初始化...
执行 @Test:测试方法2
执行 @After:测试方法后的清理...
执行 @AfterClass:全局清理...

3.3JUnit 常用的断言方法及其功能:

  1. assertEquals(expected, actual)
    验证两个值是否相等。支持基本类型和对象的比较(对象需要正确实现 equals() 方法)。
assertEquals(5, 3 + 2);  // 通过
assertEquals("hello", "hello");  // 通过
  1. assertNotEquals(unexpected, actual)
    验证两个值是否不相等。
assertNotEquals(5, 3 + 3);  // 通过
  1. assertTrue(condition)
    验证条件是否为 true。
assertTrue(5 > 3);  // 通过
  1. assertFalse(condition)
    验证条件是否为 false。
assertFalse(5 < 3);  // 通过
  1. assertNull(object)
    验证对象是否为 null。
assertNull(null);  // 通过
  1. assertNotNull(object)
    验证对象是否不为 null。
assertNotNull(new Object());  // 通过
  1. assertSame(expected, actual)
    验证两个对象是否引用同一个对象(比较内存地址)。
Object obj = new Object();
assertSame(obj, obj);  // 通过
  1. assertNotSame(unexpected, actual)
    验证两个对象是否不是同一个对象。
assertNotSame(new Object(), new Object());  // 通过
  1. assertArrayEquals(expectedArray, actualArray)
    验证两个数组是否相等(逐元素比较)。
int[] expected = {1, 2, 3};
int[] actual = {1, 2, 3};
assertArrayEquals(expected, actual);  // 通过
  1. fail()
    强制让测试失败,通常在某个逻辑不应该执行到的地方使用。
if (someCondition) {
    fail("不应执行到此处");
}
  1. assertThrows(expectedType, executable)
    验证某个操作是否抛出了指定类型的异常。
assertThrows(IllegalArgumentException.class, () -> {
    throw new IllegalArgumentException("异常测试");
});
  1. assertTimeout(Duration, executable)
    验证某个操作是否在指定时间内完成。
assertTimeout(Duration.ofSeconds(1), () -> {
    // 一些操作
});

3.4参数化测试

有时候我们希望对一个方法使用多组不同的输入进行测试,而不需要为每组输入编写单独的测试方法。JUnit支持参数化测试,允许我们以参数化的方式运行测试。

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.util.Arrays;
import java.util.Collection;
import static org.junit.Assert.assertEquals;

@RunWith(Parameterized.class)
public class ParameterizedTest {

    private int input1;
    private int input2;
    private int expected;

    public ParameterizedTest(int input1, int input2, int expected) {
        this.input1 = input1;
        this.input2 = input2;
        this.expected = expected;
    }

    @Parameterized.Parameters
    public static Collection<Object[]> data() {
        return Arrays.asList(new Object[][] {
            {1, 1, 2},
            {2, 3, 5},
            {3, 5, 8}
        });
    }

    @Test
    public void testAdd() {
        Calculator calculator = new Calculator();
        assertEquals(expected, calculator.add(input1, input2));
    }
}

在这个例子中,ParameterizedTest类使用了参数化测试运行器,每个测试用例会使用不同的输入值和期望结果来测试add()方法。

有兴趣的小伙伴可以关注我的公众号【知识星球站】一起讨论学习!!
在这里插入图片描述

无人识我鸿鹄志,我自翱翔九天外


http://www.kler.cn/news/358798.html

相关文章:

  • 华为OD机试真题---矩阵扩散
  • C++连接Simnow Linux API实现简单量化交易操作文档
  • Java基于SpringBoot微信小程序的跳蚤市场系统设计与实现(lw+数据库+讲解等)
  • 【MR开发】在Pico设备上接入MRTK3(一)——在Unity工程中导入MRTK3依赖
  • PDF工具类源码
  • DML、DDL语句中的相关操作
  • 同济子豪兄--传统图机器学习的特征工程-全图【斯坦福CS224W】
  • Qml----webengine打开的页面根据系统时区修改,javascript同理
  • Linux网络:序列化与反序列化
  • 两个字符串的最长 公共子序列
  • 【日志】力扣刷题——买卖股票的最佳时机 // Unity——添加数据表文件、EPPlus插件以及编辑器开发生成Excel转Json代码文件复习
  • 在Python中使用连接池
  • 大厂面试真题-说一下Kafka的分区再均衡机制
  • 【从零开发Mybatis】引入MapperConfig.xml和Mapper映射配置
  • LDRA Testbed软件安装教程_超详细的保姆级安装指南
  • C#笔记(1)
  • 10.21盘面理解及整理
  • 第十三章 Python 模块详解
  • disql 增量备份SQL脚本DM7/DM8
  • Chromium form表单post提交过程分析c++