1.什么是单元测试?
单元测试是测试代码的最小单元,通常针对单个类或方法。单元测试旨在验证代码是否按预期运行,帮助发现潜在的逻辑错误和bug。一个好的单元测试应该具备以下特点:
- 独立性:每个测试应该独立执行,互不依赖。
- 快速性:单元测试应该快速运行,以便能够频繁地执行。
- 可重复性:测试结果应该稳定且可重复。
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:
publicclassCalculator{publicintadd(int a,int b){return a + b;}publicintsubtract(int a,int b){return a - b;}}
测试类 CalculatorTest.java:
importorg.junit.Test;importstaticorg.junit.Assert.assertEquals;publicclassCalculatorTest{@TestpublicvoidtestAdd(){Calculator calculator =newCalculator();int result = calculator.add(2,3);assertEquals(5, result);// 断言结果应该为5}@TestpublicvoidtestSubtract(){Calculator calculator =newCalculator();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:忽略指定的测试方法。
例如:
importorg.junit.*;publicclassJUnitExample{// 在所有测试方法之前执行,仅执行一次@BeforeClasspublicstaticvoidsetUpBeforeClass()throwsException{System.out.println("执行 @BeforeClass:全局初始化...");}// 在所有测试方法之后执行,仅执行一次@AfterClasspublicstaticvoidtearDownAfterClass()throwsException{System.out.println("执行 @AfterClass:全局清理...");}// 在每个测试方法之前执行@BeforepublicvoidsetUp()throwsException{System.out.println("执行 @Before:测试方法前的初始化...");}// 在每个测试方法之后执行@AfterpublicvoidtearDown()throwsException{System.out.println("执行 @After:测试方法后的清理...");}// 标记为测试方法@TestpublicvoidtestMethod1(){System.out.println("执行 @Test:测试方法1");Assert.assertEquals(1,1);}// 标记为测试方法@TestpublicvoidtestMethod2(){System.out.println("执行 @Test:测试方法2");Assert.assertTrue(true);}// 忽略此测试方法@Ignore("此测试方法被忽略")@TestpublicvoidignoredTestMethod(){System.out.println("此测试方法应该不会被执行");}}
输出:
执行 @BeforeClass:全局初始化...
执行 @Before:测试方法前的初始化...
执行 @Test:测试方法1
执行 @After:测试方法后的清理...
执行 @Before:测试方法前的初始化...
执行 @Test:测试方法2
执行 @After:测试方法后的清理...
执行 @AfterClass:全局清理...
3.3JUnit 常用的断言方法及其功能:
- assertEquals(expected, actual) 验证两个值是否相等。支持基本类型和对象的比较(对象需要正确实现 equals() 方法)。
assertEquals(5,3+2);// 通过assertEquals("hello","hello");// 通过
- assertNotEquals(unexpected, actual) 验证两个值是否不相等。
assertNotEquals(5,3+3);// 通过
- assertTrue(condition) 验证条件是否为 true。
assertTrue(5>3);// 通过
- assertFalse(condition) 验证条件是否为 false。
assertFalse(5<3);// 通过
- assertNull(object) 验证对象是否为 null。
assertNull(null);// 通过
- assertNotNull(object) 验证对象是否不为 null。
assertNotNull(newObject());// 通过
- assertSame(expected, actual) 验证两个对象是否引用同一个对象(比较内存地址)。
Object obj =newObject();assertSame(obj, obj);// 通过
- assertNotSame(unexpected, actual) 验证两个对象是否不是同一个对象。
assertNotSame(newObject(),newObject());// 通过
- assertArrayEquals(expectedArray, actualArray) 验证两个数组是否相等(逐元素比较)。
int[] expected ={1,2,3};int[] actual ={1,2,3};assertArrayEquals(expected, actual);// 通过
- fail() 强制让测试失败,通常在某个逻辑不应该执行到的地方使用。
if(someCondition){fail("不应执行到此处");}
- assertThrows(expectedType, executable) 验证某个操作是否抛出了指定类型的异常。
assertThrows(IllegalArgumentException.class,()->{thrownewIllegalArgumentException("异常测试");});
- assertTimeout(Duration, executable) 验证某个操作是否在指定时间内完成。
assertTimeout(Duration.ofSeconds(1),()->{// 一些操作});
3.4参数化测试
有时候我们希望对一个方法使用多组不同的输入进行测试,而不需要为每组输入编写单独的测试方法。JUnit支持参数化测试,允许我们以参数化的方式运行测试。
importorg.junit.Test;importorg.junit.runner.RunWith;importorg.junit.runners.Parameterized;importjava.util.Arrays;importjava.util.Collection;importstaticorg.junit.Assert.assertEquals;@RunWith(Parameterized.class)publicclassParameterizedTest{privateint input1;privateint input2;privateint expected;publicParameterizedTest(int input1,int input2,int expected){this.input1 = input1;this.input2 = input2;this.expected = expected;}@Parameterized.ParameterspublicstaticCollection<Object[]>data(){returnArrays.asList(newObject[][]{{1,1,2},{2,3,5},{3,5,8}});}@TestpublicvoidtestAdd(){Calculator calculator =newCalculator();assertEquals(expected, calculator.add(input1, input2));}}
在这个例子中,ParameterizedTest类使用了参数化测试运行器,每个测试用例会使用不同的输入值和期望结果来测试add()方法。
有兴趣的小伙伴可以关注我的公众号【知识星球站】一起讨论学习!!
无人识我鸿鹄志,我自翱翔九天外
版权归原作者 霜!! 所有, 如有侵权,请联系我们删除。