JUnit 带示例的注释教程:什么是@Test 和@After

⚡ 智能摘要

JUnit 注释是一种添加到代码中的语法元数据。 Java 源代码,以便测试运行器知道要执行哪些方法、何时执行它们以及每个方法可能需要多长时间。

  • 🔘 @测试: 标记一个公共的空方法 JUnit 作为单个测试用例执行。
  • ☑️ 生命周期: @Before 和 @After 分别包裹每个测试,而 @BeforeClass 和 @AfterClass 分别包裹类。
  • 控制: @Ignore 跳过测试,@Test(timeout) 限制运行时间,@Test(expected) 断言抛出的异常。
  • 🧪 断言: org.junit.Assert 提供 assertEquals、assertTrue、assertNull、assertSame 和 fail() 方法。
  • 🛠️ 遗产: TestCase、TestResult 和 TestSuite 属于较旧的 junit.framework 包。
  • 📊 JUnit 5: Jupiter 将这些重命名为 @BeforeEach、@AfterEach、@BeforeAll、@AfterAll 和 @Disabled。

JUnit 注解教程,涵盖 @Test、@Before 和 @After 注解。

什么是 JUnit 注释?

JUnit 注释 是一种特殊的句法元数据,可以添加到 Java 为了提高代码的可读性和结构性,源代码可以进行注解。变量、参数、包、方法和类都可以被注解。注解是在[此处应填写具体文本]中引入的。 JUnit 4,也就是 Java 代码更易读、更简洁。这就是两者之间的最大区别。 JUnit 3和 JUnit 4: JUnit 4 是基于注释的。

只要掌握了这些注解的基本知识,就可以轻松学习和实现…… JUnit 测试。以下是重要且常用的 JUnit 注释列表,以及 JUnit 每项旁边都标有 5(木星)当量:

S.No. 注释 描述 JUnit 5个当量
1. @测试 此注解取代了 junit.framework.TestCase,并表明附加到它的公共 void 方法可以作为测试用例执行。 @Test(org.junit.jupiter.api)
2. @前 如果您想在每个测试用例之前执行某些语句(例如先决条件),则可以使用此注释。 @BeforeEach
3. @课前 如果您想在所有测试用例之前执行某些语句,例如必须在所有测试用例之前打开的测试连接,则可以使用此注解。 @BeforeAll
4. @后 如果希望在每个语句之后执行一些语句,则可以使用此注释 测试用例例如重置变量或删除临时文件。 @AfterEach
5. @下课以后 如果您想在所有测试用例执行完毕后执行某些语句,例如在执行完所有测试用例后释放资源,则可以使用此注解。 @毕竟
6. @忽略 如果您想在测试执行期间忽略某些语句,例如在测试执行期间禁用某些测试用例,则可以使用此注解。 @已禁用
7. @测试(超时=500) 如果您想在测试执行期间设置一些超时时间,例如,如果您正在遵守 SLA(服务级别协议),并且测试需要在指定的时间内完成,则可以使用此注解。 @Timeout 或 assertTimeout
8. @Test(预期=IllegalArgumentException.class) 如果您想在测试执行期间处理某些异常,可以使用此注解。例如,如果您想检查某个特定方法是否抛出了指定的异常。 断言抛出异常

JUnit 注释示例

让我们创建一个涵盖重要内容的类 JUnit 用简单的打印语句注释并使用测试运行器类执行它:

步骤1) 请考虑以下事项 Java 具有各种方法的类,这些方法都附加到上面列出的注解上:

JunitAnnotations示例.java

package guru99.junit;		

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

import java.util.ArrayList;		

import org.junit.After;		
import org.junit.AfterClass;		
import org.junit.Before;		
import org.junit.BeforeClass;		
import org.junit.Ignore;		
import org.junit.Test;		

public class JunitAnnotationsExample {				

    private ArrayList<String> list;					

    @BeforeClass		
    public static void m1() {							
        System.out.println("Using @BeforeClass , executed before all test cases ");					
    }		

    @Before		
    public void m2() {					
        list = new ArrayList<String>();					
        System.out.println("Using @Before annotations ,executed before each test cases ");					
    }		

    @AfterClass		
    public static void m3() {							
        System.out.println("Using @AfterClass ,executed after all test cases");					
    }		

    @After		
    public void m4() {					
        list.clear();			
        System.out.println("Using @After ,executed after each test cases");					
    }		

    @Test		
    public void m5() {					
        list.add("test");					
        assertFalse(list.isEmpty());			
        assertEquals(1, list.size());			
    }		

    @Ignore		
    public void m6() {					
        System.out.println("Using @Ignore , this execution is ignored");					
    }		

    @Test(timeout = 10)			
    public void m7() {					
        System.out.println("Using @Test(timeout),it can be used to enforce timeout in JUnit4 test case");					
    }		

    @Test(expected = NoSuchMethodException.class)					
    public void m8() {					
        System.out.println("Using @Test(expected) ,it will check for specified exception during its execution");					

    }		

}		

步骤2) 让我们创建一个测试运行器类来执行上述测试:

测试运行器.java

package guru99.junit;		

import org.junit.runner.JUnitCore;		
import org.junit.runner.Result;		
import org.junit.runner.notification.Failure;		

public class TestRunner {				
			public static void main(String[] args) {									
      Result result = JUnitCore.runClasses(JunitAnnotationsExample.class);					
			for (Failure failure : result.getFailures()) {							
         System.out.println(failure.toString());					
      }		
      System.out.println("Result=="+result.wasSuccessful());							
   }		
}      	

预期结果

  • 所有测试用例将逐一执行,所有打印语句都可以在控制台上看到。
  • 如上表所述,@Before 和 @BeforeClass 在 JUnit [方法 m2() 和 m1()] 将分别在每个测试用例之前和所有测试用例之前执行。
  • 同样地,@After 和 @AfterClass 在 JUnit 方法 m4() 和 m3() 将分别在每个测试用例执行后和所有测试用例执行后执行。@Ignore(方法 m6())将被视为忽略该测试。

让我们分析一下上述测试用例。 Java 课程详情:

  1. 考虑如下方法 m5():
	@Test		
    public void m5() {					
        list.add("test");					
        assertFalse(list.isEmpty());			
        assertEquals(1, list.size());			
    }		

在上述方法中,您将一个字符串添加到变量“list”中:

  • 列表.isEmpty() 将返回 false。
  • 断言False(列表.isEmpty()) 必须返回 true。
  • 因此,测试用例将 通过.

由于您只向列表中添加了一个字符串,因此列表大小为 1。

  • 列表.大小() 必须返回整数值“1”。
  • So 断言Equals(1,列表.size()) 必须返回 true。
  • 因此,测试用例将 通过.
  1. 考虑如下方法 m7():
@Test(timeout = 10)		
    public void m7() {					
        System.out.println("Using @Test(timeout),it can be used to enforce timeout in JUnit4 test case");					
    }		

如上所述, @测试(超时=10) 用于在测试用例中强制执行超时。该值以毫秒为单位,因此 m7() 必须在 10 毫秒内完成。

  1. 考虑如下方法 m8():
@Test(expected = NoSuchMethodException.class)				
    public void m8() {					
        System.out.println("Using @Test(expected) ,it will check for specified exception during its execution");					
    
    }		

如上所述, @Test(预期) 执行过程中会检查指定的异常,因此方法 m8() 将抛出“No Such Method Exception”异常。结果,测试将异常执行。

准确性说明: m8() 函数只会打印一行,因此声明的异常实际上永远不会被抛出。 JUnit 4 报告测试失败。请将预期类型与方法实际抛出的类型进行匹配。 JUnit 5 用 断言抛出异常.

由于所有测试用例都通过,因此测试执行成功。

实际结果

由于上述示例中有三个测试用例,因此所有测试用例将逐一执行。请参见下面的控制台屏幕截图:

Eclipse 控制台输出显示了 @BeforeClass、@Before、@After 和 @AfterClass 的打印语句
JunitAnnotationsExample 生成的控制台输出

请参阅以下可在控制台上看到的打印语句:

使用 @BeforeClass ,在所有测试用例之前执行

使用@Before注解,在每个测试用例之前执行

使用@After,在每个测试用例之后执行

使用@Before注解,在每个测试用例之前执行

使用@Test(timeout),可以强制执行超时 JUnit4 测试用例

使用@After,在每个测试用例之后执行

使用@Before注解,在每个测试用例之前执行

使用@Test(expected),它将在执行过程中检查指定的异常

使用@After,在每个测试用例之后执行

使用@AfterClass,在所有测试用例之后执行

JUnit 断言类

注解决定方法何时执行;断言方法决定断言是否通过。

这个类提供了一系列断言方法,这些方法对于编写测试用例非常有用。如果所有断言语句都通过,则测试结果成功。如果任何一个断言语句失败,则测试结果失败。 JUnit 断言 教程深入讲解了每种方法。

如前所述,下表描述了重要的断言方法及其说明:

S.No. 付款方式 描述
1. void assertEquals(布尔预期,布尔实际) 它检查两个值是否相等,类似于 Object 类的 equals 方法。
2. void assertFalse(布尔条件) 功能是检查某个条件是否为假。
3. void assertNotNull(Object 对象) “assertNotNull” 功能用于检查对象是否为空。
4. void assertNull(Object 对象) “assertNull” 功能是检查对象是否为空。
5. void assertTrue(布尔条件) “assertTrue”功能用于检查条件是否正确。
6. 无效失败() 如果你想抛出一个断言错误,fail() 总是会导致失败的结果。
7. void assertSame([字符串消息] “assertSame”功能是检查两个对象是否引用同一个对象。
8. void assertNotSame([字符串消息] “assertNotSame”功能用于检查两个对象是否引用同一个对象。

JUnit 测试用例类

要运行多个测试,可以使用 TestCase 类。 junit.framework 包。@Test 注解告诉 JUnit 这个公共 void 方法(这里是一个测试用例)可以作为测试用例运行。

版本说明: 测试用例, 测试结果测试套件 属于遗产 junit.framework 包从 JUnit 3. 它们仍然包含在 JUnit 4.x 工件中,但基于注解的测试不会扩展 TestCase。

下表列出了一些可用的重要方法 junit.framework.TestCase 类:

S.No. 付款方式 描述
1. int countTestCases() 此方法用于统计执行了多少个测试用例。 运行(测试结果 tr) 方法。
2. 测试结果创建结果() 此方法用于创建 测试结果 目的。
3. 字符串获取名称() 此方法返回一个字符串,它只不过是一个 测试用例 名称。
4. 测试结果运行() 此方法用于执行测试,该测试返回一个结果。 测试结果 目的。
5. void run(TestResult 结果) 此方法用于执行具有 测试结果 对象,不返回任何值。
6. 无效设置名称(字符串名称) 此方法用于设置名称 测试用例。
7. 无效设置() 此方法用于编写资源关联代码,例如创建数据库连接。
8. 无效拆卸() 此方法用于编写资源释放代码,例如在执行事务操作后释放数据库连接。

JUnit TestResult 类

执行测试时,它会返回一个结果(以以下形式): 测试结果 对象)。此 TestResult 对象可用于分析结果对象。此测试结果可以是失败或成功。

下表列出了 junit.framework.TestResult 类中使用的一些重要方法:

S.No. 付款方式 描述
1. void addError(测试测试,Throwable t) 如果您需要在测试中添加错误,可以使用此方法。
2. void addFailure(测试测试,AssertionFailedError t) 如果您需要将某个故障添加到故障列表中,可以使用此方法。
3. void endTest(测试测试) 此方法用于通知测试已执行(完成)。
4. int 错误计数() 此方法用于获取测试执行过程中检测到的错误。
5. 枚举错误() 此方法仅返回一个错误集合(此处为枚举)。
6. int 失败次数() 此方法用于获取测试执行期间检测到的故障数量。
7. void run(TestCase 测试) 此方法用于执行测试用例。
8. int 运行次数() 此方法仅统计已执行的测试次数。
9. void startTest(测试测试) 该方法用于通知测试已开始。
10. 无效停止() 此方法用于停止测试运​​行。

JUnit 测试套件类

如果你想按指定顺序执行多个测试,可以将所有测试合并到一个地方。这个地方称为测试套件。 JUnit 测试套件 教程将逐步讲解完整示例。

请参阅下表,了解其中使用的重要方法。 junit.framework.TestSuite 类:

S.No. 付款方式 描述
1. void addTest(测试测试) 如果您想向套件中添加测试,可以使用此方法。
2. void addTestSuite(类测试类) 如果您想在向套件添加测试时指定类,则使用此方法。
3. int countTestCases() 如果要计算测试用例的数量,可以使用此方法。
4. 字符串获取名称() 该方法用于获取测试套件的名称。
5. void run(TestResult 结果) 此方法用于执行测试并将测试结果收集到一个文件中。 测试结果 目的。
6. 无效设置名称(字符串名称) 此方法用于设置名称 测试套件.
7. 测试 testAt(int 索引) 如果您想返回给定索引处的测试,可以使用此方法。
8. int 测试计数() 如果您想返回测试套件中的测试数量,可以使用此方法。
9. 静态测试警告(字符串消息) 此方法返回一个将失败并记录警告消息的测试。

常见问题

是的。一个方法通常会同时使用 `@Test` 和 `@Ignore` 注解,或者同时使用 `@Test` 注解、超时时间和预期异常。你不能在一个方法上叠加两个生命周期注解,例如 `@Before` 和 `@After`。

@Ignore 仅抑制方法 JUnit 它已被识别为测试。如果没有 @Test 注解,运行器就不会收集该方法,因此它既不会被运行,也不会被列为已跳过。

JUnit 该方法在单独的线程上运行,一旦超时,就会抛出 TestTimedOutException 异常。线程会被中断而不是终止,因此阻塞调用可能会持续运行。

只能通过复古引擎。添加 junit-vintage-engine 可以实现 JUnit 平台运行现有的 org.junit 测试无需任何更改,但 Jupiter 测试必须导入 org.junit.jupiter.api。在一个类中混合使用这两种导入集会失败。

仅用于维护。在旧代码库中,继承自 TestCase 并构建 TestSuite 对象的旧版测试套件仍然很常见,因此了解 API 有助于维护。新测试应基于注解。

JUnit 它会为每个测试方法创建一个新的测试类实例,因此在运行类级设置时不会存在已存在的实例。静态方法不需要实例。 JUnit 拒绝非静态声明。

AI 助手会读取被测方法,并建议设置语句应该放在 @Before 还是 @BeforeClass 注解中,以及失败处理路径是否需要 @Test(expected) 或 assertThrows 注解。请将每个建议都视为草稿。

GitHub 副驾驶 通常能正确放置安装和拆卸步骤,但经常混淆。 JUnit 4 和 Jupiter 导入在一个文件中。运行测试套件之前,请检查导入代码块。

总结一下这篇文章: