- JUnit 教程
- JUnit - 首页
- JUnit - 概述
- JUnit - 环境搭建
- JUnit - 测试框架
- JUnit - 基本用法
- JUnit - API
- JUnit - 编写测试
- JUnit - 使用断言
- JUnit - 执行流程
- JUnit - 执行测试
- JUnit - 套件测试
- JUnit - 忽略测试
- JUnit - 时间测试
- JUnit - 异常测试
- JUnit - 参数化测试
- JUnit - 与 Ant 集成
- JUnit - 与 Eclipse 集成
- JUnit - 扩展
- JUnit 有用资源
- JUnit - 常见问题解答
- JUnit 快速指南
- JUnit - 有用资源
- JUnit - 讨论
JUnit 快速指南
JUnit - 概述
测试是检查应用程序功能以确保其按要求运行的过程。单元测试在开发人员层面发挥作用;它是对单个实体(类或方法)的测试。单元测试在帮助软件公司向客户交付高质量产品方面发挥着关键作用。
单元测试可以通过两种方式完成:手动测试和自动化测试。
手动测试 | 自动化测试 |
---|---|
在没有任何工具支持的情况下手动执行测试用例称为手动测试。 | 利用工具支持并使用自动化工具执行测试用例称为自动化测试。 |
耗时且繁琐 - 由于测试用例由人力资源执行,因此速度非常慢且繁琐。 | 快速 - 自动化运行测试用例的速度比人力资源快得多。 |
人力资源投入巨大 - 由于需要手动执行测试用例,因此手动测试需要更多测试人员。 | 人力资源投入较少 - 测试用例使用自动化工具执行,因此自动化测试需要较少的测试人员。 |
可靠性较低 - 手动测试的可靠性较低,因为它必须考虑人为错误。 | 可靠性更高 - 自动化测试精确且可靠。 |
不可编程 - 无法进行编程来编写复杂的测试以获取隐藏信息。 | 可编程 - 测试人员可以编写复杂的测试来获取隐藏信息。 |
什么是 JUnit?
JUnit 是 Java 编程语言的单元测试框架。它在测试驱动开发中扮演着至关重要的角色,并且是统称为 xUnit 的单元测试框架家族的一员。
JUnit 推崇“先测试后编码”的理念,强调首先为一段代码设置测试数据,然后进行测试,再进行实现。这种方法类似于“测试一点,编码一点,测试一点,编码一点”。它提高了程序员的生产力和程序代码的稳定性,从而减少了程序员的压力和调试时间。
JUnit 的特点
JUnit 是一个开源框架,用于编写和运行测试。
提供注解来标识测试方法。
提供断言来测试预期结果。
提供测试运行器来运行测试。
JUnit 测试允许您更快地编写代码,从而提高质量。
JUnit 简洁优雅。它不复杂且耗时较少。
JUnit 测试可以自动运行,它们检查自己的结果并提供即时反馈。无需手动检查测试结果报告。
JUnit 测试可以组织成包含测试用例甚至其他测试套件的测试套件。
JUnit 在进度条中显示测试进度,如果测试运行顺利,则为绿色;如果测试失败,则变为红色。
什么是单元测试用例?
单元测试用例是代码的一部分,它确保另一部分代码(方法)按预期工作。为了快速获得所需结果,需要一个测试框架。JUnit 是 Java 编程语言的理想单元测试框架。
正式编写的单元测试用例的特点是已知的输入和预期的输出,这些在测试执行之前就已确定。已知的输入应该测试前提条件,而预期的输出应该测试后置条件。
每个需求至少必须有两个单元测试用例:一个正测试和一个负测试。如果一个需求有子需求,则每个子需求必须至少有两个测试用例作为正测试和负测试。
JUnit - 环境搭建
本地环境搭建
JUnit 是一个 Java 框架,因此首要要求是在您的机器上安装 JDK。
系统要求
JDK | 1.5 或更高版本。 |
---|---|
内存 | 无最低要求。 |
磁盘空间 | 无最低要求。 |
操作系统 | 无最低要求。 |
步骤 1:验证您的机器上是否安装了 Java
首先,打开控制台并根据您正在使用的操作系统执行 java 命令。
操作系统 | 任务 | 命令 |
---|---|---|
Windows | 打开命令控制台 | c:\> java -version |
Linux | 打开命令终端 | $ java -version |
Mac | 打开终端 | machine:~ joseph$ java -version |
让我们验证所有操作系统的输出:
操作系统 | 输出 |
---|---|
Windows | java version "1.8.0_101" Java(TM) SE Runtime Environment (build 1.8.0_101) |
Linux | java version "1.8.0_101" Java(TM) SE Runtime Environment (build 1.8.0_101) |
Mac | java version "1.8.0_101" Java(TM) SE Runtime Environment (build 1.8.0_101) |
如果您的系统上未安装 Java,请从以下链接下载 Java 软件开发工具包 (SDK) https://www.oracle.com。在本教程中,我们假设已安装 Java 1.8.0_101 版本。
步骤 2:设置 JAVA 环境
设置JAVA_HOME环境变量以指向 Java 安装在您机器上的基目录位置。例如:
操作系统 | 输出 |
---|---|
Windows | 将环境变量 JAVA_HOME 设置为 C:\Program Files\Java\jdk1.8.0_101 |
Linux | export JAVA_HOME = /usr/local/java-current |
Mac | export JAVA_HOME = /Library/Java/Home |
将 Java 编译器位置添加到系统路径。
操作系统 | 输出 |
---|---|
Windows | 在系统变量Path的末尾附加字符串C:\Program Files\Java\jdk1.8.0_101\bin。 |
Linux | export PATH = $PATH:$JAVA_HOME/bin/ |
Mac | 不需要 |
使用上面解释的命令java -version验证 Java 安装。
步骤 3:下载 JUnit 归档文件
从http://www.junit.org下载最新版本的 JUnit jar 文件。在撰写本教程时,我们已下载 Junit-4.12.jar 并将其复制到 C:\>JUnit 文件夹。
操作系统 | 归档文件名 |
---|---|
Windows | junit4.12.jar |
Linux | junit4.12.jar |
Mac | junit4.12.jar |
步骤 4:设置 JUnit 环境
设置JUNIT_HOME环境变量以指向 JUNIT jar 存储在您机器上的基目录位置。假设我们将 junit4.12.jar 存储在 JUNIT 文件夹中。
序号 | 操作系统和说明 |
---|---|
1 | Windows 将环境变量 JUNIT_HOME 设置为 C:\JUNIT |
2 | Linux export JUNIT_HOME = /usr/local/JUNIT |
3 | Mac export JUNIT_HOME = /Library/JUNIT |
步骤 5:设置 CLASSPATH 变量
设置CLASSPATH环境变量以指向 JUNIT jar 位置。
序号 | 操作系统和说明 |
---|---|
1 | Windows 将环境变量 CLASSPATH 设置为 %CLASSPATH%;%JUNIT_HOME%\junit4.12.jar;.; |
2 | Linux export CLASSPATH = $CLASSPATH:$JUNIT_HOME/junit4.12.jar:. |
3 | Mac export CLASSPATH = $CLASSPATH:$JUNIT_HOME/junit4.12.jar:. |
步骤 6:测试 JUnit 设置
在C:\>JUNIT_WORKSPACE中创建一个名为 TestJunit 的 Java 类文件。
import org.junit.Test; import static org.junit.Assert.assertEquals; public class TestJunit { @Test public void testAdd() { String str = "Junit is working fine"; assertEquals("Junit is working fine",str); } }
在C:\>JUNIT_WORKSPACE中创建一个名为 TestRunner 的 Java 类文件来执行测试用例。
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(TestJunit.class); for (Failure failure : result.getFailures()) { System.out.println(failure.toString()); } System.out.println(result.wasSuccessful()); } }
步骤 7:验证结果
使用javac编译器编译类,如下所示:
C:\JUNIT_WORKSPACE>javac TestJunit.java TestRunner.java
现在运行 Test Runner 以查看结果,如下所示:
C:\JUNIT_WORKSPACE>java TestRunner
验证输出。
true
JUnit - 测试框架
JUnit 是开发人员用来在 Java 中实现单元测试并加快编程速度和提高代码质量的回归测试框架。JUnit 框架可以轻松地与以下任何一个集成:
- Eclipse
- Ant
- Maven
JUnit 测试框架的特点
JUnit 测试框架提供以下重要功能:
- 夹具
- 测试套件
- 测试运行器
- JUnit 类
夹具
夹具是一组对象的固定状态,用作运行测试的基线。测试夹具的目的是确保有一个众所周知的固定环境来运行测试,以便结果可重复。它包括:
- setUp() 方法,在每次测试调用之前运行。
- tearDown() 方法,在每次测试方法之后运行。
让我们检查一个例子:
import junit.framework.*; public class JavaTest extends TestCase { protected int value1, value2; // assigning the values protected void setUp(){ value1 = 3; value2 = 3; } // test method to add two values public void testAdd(){ double result = value1 + value2; assertTrue(result == 6); } }
测试套件
测试套件捆绑了一些单元测试用例并一起运行它们。在 JUnit 中,@RunWith 和 @Suite 注解都用于运行套件测试。下面是一个使用 TestJunit1 和 TestJunit2 测试类的示例。
import org.junit.runner.RunWith; import org.junit.runners.Suite; //JUnit Suite Test @RunWith(Suite.class) @Suite.SuiteClasses({ TestJunit1.class ,TestJunit2.class }) public class JunitTestSuite { }
import org.junit.Test; import org.junit.Ignore; import static org.junit.Assert.assertEquals; public class TestJunit1 { String message = "Robert"; MessageUtil messageUtil = new MessageUtil(message); @Test public void testPrintMessage() { System.out.println("Inside testPrintMessage()"); assertEquals(message, messageUtil.printMessage()); } }
import org.junit.Test; import org.junit.Ignore; import static org.junit.Assert.assertEquals; public class TestJunit2 { String message = "Robert"; MessageUtil messageUtil = new MessageUtil(message); @Test public void testSalutationMessage() { System.out.println("Inside testSalutationMessage()"); message = "Hi!" + "Robert"; assertEquals(message,messageUtil.salutationMessage()); } }
测试运行器
测试运行器用于执行测试用例。这是一个假设测试类TestJunit已经存在的示例。
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(TestJunit.class); for (Failure failure : result.getFailures()) { System.out.println(failure.toString()); } System.out.println(result.wasSuccessful()); } }
JUnit 类
JUnit 类是在编写和测试 JUnit 中使用的重要类。一些重要的类包括:
Assert - 包含一组断言方法。
TestCase - 包含一个测试用例,该用例定义了运行多个测试的夹具。
TestResult - 包含用于收集执行测试用例结果的方法。
JUnit - 基本用法
现在让我们来看一个基本的例子来演示使用 JUnit 的逐步过程。
创建类
创建一个要测试的 Java 类,例如,在C:\>JUNIT_WORKSPACE中创建 MessageUtil.java
/* * This class prints the given message on console. */ public class MessageUtil { private String message; //Constructor //@param message to be printed public MessageUtil(String message){ this.message = message; } // prints the message public String printMessage(){ System.out.println(message); return message; } }
创建测试用例类
- 创建一个 Java 测试类,例如,TestJunit.java。
- 向您的测试类添加一个测试方法 testPrintMessage()。
- 向方法 testPrintMessage() 添加一个注解 @Test。
- 实现测试条件并使用 JUnit 的 assertEquals API 检查条件。
在C:\>JUNIT_WORKSPACE中创建一个名为 TestJunit.java 的 Java 类文件。
import org.junit.Test; import static org.junit.Assert.assertEquals; public class TestJunit { String message = "Hello World"; MessageUtil messageUtil = new MessageUtil(message); @Test public void testPrintMessage() { assertEquals(message,messageUtil.printMessage()); } }
创建测试运行器类
- 创建一个 TestRunner Java 类。
- 使用 JUnit 的 JUnitCore 类的 runClasses 方法运行上面创建的测试类的测试用例。
- 获取 Result 对象中运行的测试用例的结果。
- 使用 Result 对象的 getFailures() 方法获取失败。
- 使用 Result 对象的 wasSuccessful() 方法获取成功结果。
在C:\>JUNIT_WORKSPACE中创建一个名为 TestRunner.java 的 Java 类文件来执行测试用例。
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(TestJunit.class); for (Failure failure : result.getFailures()) { System.out.println(failure.toString()); } System.out.println(result.wasSuccessful()); } }
使用 javac 编译 MessageUtil、测试用例和测试运行器类。
C:\JUNIT_WORKSPACE>javac MessageUtil.java TestJunit.java TestRunner.java
现在运行 Test Runner,它将运行在提供的测试用例类中定义的测试用例。
C:\JUNIT_WORKSPACE>java TestRunner
验证输出。
Hello World true
现在更新C:\>JUNIT_WORKSPACE中的 TestJunit,以便测试失败。更改消息字符串。
import org.junit.Test; import static org.junit.Assert.assertEquals; public class TestJunit { String message = "Hello World"; MessageUtil messageUtil = new MessageUtil(message); @Test public void testPrintMessage() { message = "New Word"; assertEquals(message,messageUtil.printMessage()); } }
让我们保持其余类不变,并尝试运行相同的 Test Runner。
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(TestJunit.class); for (Failure failure : result.getFailures()) { System.out.println(failure.toString()); } System.out.println(result.wasSuccessful()); } }
现在运行 Test Runner,它将运行在提供的测试用例类中定义的测试用例。
C:\JUNIT_WORKSPACE>java TestRunner
验证输出。
Hello World testPrintMessage(TestJunit): expected:<[New Wor]d> but was:<[Hello Worl]d> false
JUnit - API
JUnit 中最重要的包是junit.framework,它包含所有核心类。一些重要的类如下:
序号 | 类名 | 功能 |
---|---|---|
1 | Assert | 一组断言方法。 |
2 | TestCase | 测试用例定义了运行多个测试的夹具。 |
3 | TestResult(测试结果) | TestResult 收集执行测试用例的结果。 |
4 | TestSuite(测试套件) | TestSuite 是测试的组合。 |
Assert 类(断言类)
以下是 **org.junit.Assert** 类的声明:
public class Assert extends java.lang.Object
此类提供了一组用于编写测试的有用断言方法。只有失败的断言才会被记录。Assert 类的一些重要方法如下:
序号 | 方法和描述 |
---|---|
1 | void assertEquals(boolean expected, boolean actual) 检查两个基本类型/对象是否相等。 |
2 | void assertFalse(boolean condition) 检查条件是否为假。 |
3 | void assertNotNull(Object object) 检查对象是否不为空。 |
4 | void assertNull(Object object) 检查对象是否为空。 |
5 | void assertTrue(boolean condition) 检查条件是否为真。 |
6 | void fail() 测试失败,无消息。 |
让我们在示例中使用上面提到的某些方法。在 **C:\>JUNIT_WORKSPACE** 中创建一个名为 TestJunit1.java 的 Java 类文件。
import org.junit.Test; import static org.junit.Assert.*; public class TestJunit1 { @Test public void testAdd() { //test data int num = 5; String temp = null; String str = "Junit is working fine"; //check for equality assertEquals("Junit is working fine", str); //check for false condition assertFalse(num > 6); //check for not null value assertNotNull(temp); } }
接下来,在 C:\>JUNIT_WORKSPACE 中创建一个名为 **TestRunner1.java** 的 Java 类文件来执行测试用例。
import org.junit.runner.JUnitCore; import org.junit.runner.Result; import org.junit.runner.notification.Failure; public class TestRunner1 { public static void main(String[] args) { Result result = JUnitCore.runClasses(TestJunit1.class); for (Failure failure : result.getFailures()) { System.out.println(failure.toString()); } System.out.println(result.wasSuccessful()); } }
使用 javac 编译测试用例和测试运行器类。
C:\JUNIT_WORKSPACE>javac TestJunit1.java TestRunner1.java
现在运行 Test Runner,它将运行在提供的测试用例类中定义的测试用例。
C:\JUNIT_WORKSPACE>java TestRunner1
验证输出。
true
TestCase 类(测试用例类)
以下是 **org.junit.TestCase** 类的声明:
public abstract class TestCase extends Assert implements Test
测试用例定义了运行多个测试的夹具。**TestCase** 类的一些重要方法如下:
序号 | 方法和描述 |
---|---|
1 | int countTestCases() 计算 run(TestResult result) 执行的测试用例数量。 |
2 | TestResult createResult() 创建一个默认的 TestResult 对象。 |
3 | String getName() 获取 TestCase 的名称。 |
4 | TestResult run() 一个方便的方法来运行此测试,使用默认的 TestResult 对象收集结果。 |
5 | void run(TestResult result) 运行测试用例并将结果收集到 TestResult 中。 |
6 | void setName(String name) 设置 TestCase 的名称。 |
7 | void setUp() 设置夹具,例如,打开网络连接。 |
8 | void tearDown() 拆除夹具,例如,关闭网络连接。 |
9 | String toString() 返回测试用例的字符串表示形式。 |
让我们在示例中使用上面提到的某些方法。在 **C:\>JUNIT_WORKSPACE** 中创建一个名为 **TestJunit2.java** 的 Java 类文件。
import junit.framework.TestCase; import org.junit.Before; import org.junit.Test; public class TestJunit2 extends TestCase { protected double fValue1; protected double fValue2; @Before public void setUp() { fValue1 = 2.0; fValue2 = 3.0; } @Test public void testAdd() { //count the number of test cases System.out.println("No of Test Case = "+ this.countTestCases()); //test getName String name = this.getName(); System.out.println("Test Case Name = "+ name); //test setName this.setName("testNewAdd"); String newName = this.getName(); System.out.println("Updated Test Case Name = "+ newName); } //tearDown used to close the connection or clean up activities public void tearDown( ) { } }
接下来,在 C:\>JUNIT_WORKSPACE 中创建一个名为 **TestRunner2.java** 的 Java 类文件来执行测试用例。
import org.junit.runner.JUnitCore; import org.junit.runner.Result; import org.junit.runner.notification.Failure; public class TestRunner2 { public static void main(String[] args) { Result result = JUnitCore.runClasses(TestJunit2.class); for (Failure failure : result.getFailures()) { System.out.println(failure.toString()); } System.out.println(result.wasSuccessful()); } }
使用 javac 编译测试用例和测试运行器类。
C:\JUNIT_WORKSPACE>javac TestJunit2.java TestRunner2.java
现在运行 Test Runner,它将运行在提供的测试用例类中定义的测试用例。
C:\JUNIT_WORKSPACE>java TestRunner2
验证输出。
No of Test Case = 1 Test Case Name = testAdd Updated Test Case Name = testNewAdd true
TestResult 类(测试结果类)
以下是 **org.junit.TestResult** 类的声明:
public class TestResult extends Object
TestResult 收集执行测试用例的结果。它是收集参数模式的一个实例。测试框架区分失败和错误。失败是预期的,并通过断言进行检查。错误是意外的问题,例如 ArrayIndexOutOfBoundsException。**TestResult** 类的一些重要方法如下:
序号 | 方法和描述 |
---|---|
1 | void addError(Test test, Throwable t) 向错误列表中添加错误。 |
2 | void addFailure(Test test, AssertionFailedError t) 向失败列表中添加失败。 |
3 | void endTest(Test test) 通知结果测试已完成。 |
4 | int errorCount() 获取检测到的错误数量。 |
5 | Enumeration 返回错误的枚举。 |
6 | int failureCount() 获取检测到的失败数量。 |
7 | void run(TestCase test) 运行 TestCase。 |
8 | int runCount() 获取已运行测试的数量。 |
9 | void startTest(Test test) 通知结果将要启动测试。 |
10 | void stop() 标记测试运行应该停止。 |
在 **C:\>JUNIT_WORKSPACE** 中创建一个名为 **TestJunit3.java** 的 Java 类文件。
import org.junit.Test; import junit.framework.AssertionFailedError; import junit.framework.TestResult; public class TestJunit3 extends TestResult { // add the error public synchronized void addError(Test test, Throwable t) { super.addError((junit.framework.Test) test, t); } // add the failure public synchronized void addFailure(Test test, AssertionFailedError t) { super.addFailure((junit.framework.Test) test, t); } @Test public void testAdd() { // add any test } // Marks that the test run should stop. public synchronized void stop() { //stop the test here } }
接下来,在 C:\>JUNIT_WORKSPACE 中创建一个名为 **TestRunner3.java** 的 Java 类文件来执行测试用例。
import org.junit.runner.JUnitCore; import org.junit.runner.Result; import org.junit.runner.notification.Failure; public class TestRunner3 { public static void main(String[] args) { Result result = JUnitCore.runClasses(TestJunit3.class); for (Failure failure : result.getFailures()) { System.out.println(failure.toString()); } System.out.println(result.wasSuccessful()); } }
使用 javac 编译测试用例和测试运行器类。
C:\JUNIT_WORKSPACE>javac TestJunit3.java TestRunner3.java
现在运行 Test Runner,它将运行在提供的测试用例类中定义的测试用例。
C:\JUNIT_WORKSPACE>java TestRunner3
验证输出。
true
TestSuite 类(测试套件类)
以下是 **org.junit.TestSuite** 类的声明
public class TestSuite extends Object implements Test
TestSuite 是测试的组合。它运行一系列测试用例。**TestSuite** 类的一些重要方法如下:
序号 | 方法和描述 |
---|---|
1 | void addTest(Test test) 向套件中添加测试。 |
2 | void addTestSuite(Class extends TestCase> testClass) 将给定类中的测试添加到套件中。 |
3 | int countTestCases() 计算此测试将运行的测试用例数量。 |
4 | String getName() 返回套件的名称。 |
5 | void run(TestResult result) 运行测试并将结果收集到 TestResult 中。 |
6 | void setName(String name) 设置套件的名称。 |
7 | Test testAt(int index) 返回给定索引处的测试。 |
8 | int testCount() 返回此套件中的测试数量。 |
9 | static Test warning(String message) 返回一个将失败并记录警告消息的测试。 |
在 **C:\>JUNIT_WORKSPACE** 中创建一个名为 **JunitTestSuite.java** 的 Java 类文件来创建测试套件。
import junit.framework.*; public class JunitTestSuite { public static void main(String[] a) { // add the test's in the suite TestSuite suite = new TestSuite(TestJunit1.class, TestJunit2.class, TestJunit3.class ); TestResult result = new TestResult(); suite.run(result); System.out.println("Number of test cases = " + result.runCount()); } }
使用 javac 编译测试套件类。
C:\JUNIT_WORKSPACE>javac JunitTestSuite.java
现在运行测试套件。
C:\JUNIT_WORKSPACE>java JunitTestSuite
验证输出。
No of Test Case = 1 Test Case Name = testAdd Updated Test Case Name = testNewAdd Number of test cases = 3
JUnit - 编写测试
在这里,我们将看到一个使用 POJO 类、业务逻辑类和测试类的 JUnit 测试完整示例,测试运行器将运行该示例。
在 **C:\>JUNIT_WORKSPACE** 中创建 **EmployeeDetails.java**,这是一个 POJO 类。
public class EmployeeDetails { private String name; private double monthlySalary; private int age; /** * @return the name */ public String getName() { return name; } /** * @param name the name to set */ public void setName(String name) { this.name = name; } /** * @return the monthlySalary */ public double getMonthlySalary() { return monthlySalary; } /** * @param monthlySalary the monthlySalary to set */ public void setMonthlySalary(double monthlySalary) { this.monthlySalary = monthlySalary; } /** * @return the age */ public int getAge() { return age; } /** * @param age the age to set */ public void setAge(int age) { this.age = age; } }
**EmployeeDetails** 类用于:
- 获取/设置员工姓名。
- 获取/设置员工月薪。
- 获取/设置员工年龄。
在 **C:\>JUNIT_WORKSPACE** 中创建一个名为 **EmpBusinessLogic.java** 的文件,其中包含业务逻辑。
public class EmpBusinessLogic { // Calculate the yearly salary of employee public double calculateYearlySalary(EmployeeDetails employeeDetails) { double yearlySalary = 0; yearlySalary = employeeDetails.getMonthlySalary() * 12; return yearlySalary; } // Calculate the appraisal amount of employee public double calculateAppraisal(EmployeeDetails employeeDetails) { double appraisal = 0; if(employeeDetails.getMonthlySalary() < 10000){ appraisal = 500; }else{ appraisal = 1000; } return appraisal; } }
**EmpBusinessLogic** 类用于计算:
- 员工的年薪。
- 员工的考核金额。
在 **C:\>JUNIT_WORKSPACE** 中创建一个名为 **TestEmployeeDetails.java** 的文件,其中包含要测试的测试用例。
import org.junit.Test; import static org.junit.Assert.assertEquals; public class TestEmployeeDetails { EmpBusinessLogic empBusinessLogic = new EmpBusinessLogic(); EmployeeDetails employee = new EmployeeDetails(); //test to check appraisal @Test public void testCalculateAppriasal() { employee.setName("Rajeev"); employee.setAge(25); employee.setMonthlySalary(8000); double appraisal = empBusinessLogic.calculateAppraisal(employee); assertEquals(500, appraisal, 0.0); } // test to check yearly salary @Test public void testCalculateYearlySalary() { employee.setName("Rajeev"); employee.setAge(25); employee.setMonthlySalary(8000); double salary = empBusinessLogic.calculateYearlySalary(employee); assertEquals(96000, salary, 0.0); } }
**TestEmployeeDetails** 类用于测试 **EmpBusinessLogic** 类的函数。它
- 测试员工的年薪。
- 测试员工的考核金额。
接下来,在 **C:\>JUNIT_WORKSPACE** 中创建一个名为 **TestRunner.java** 的 Java 类文件来执行测试用例。
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(TestEmployeeDetails.class); for (Failure failure : result.getFailures()) { System.out.println(failure.toString()); } System.out.println(result.wasSuccessful()); } }
使用 javac 编译测试用例和测试运行器类。
C:\JUNIT_WORKSPACE>javac EmployeeDetails.java EmpBusinessLogic.java TestEmployeeDetails.java TestRunner.java
现在运行 Test Runner,它将运行在提供的测试用例类中定义的测试用例。
C:\JUNIT_WORKSPACE>java TestRunner
验证输出。
true
JUnit - 使用断言
断言
所有断言都在 Assert 类中。
public class Assert extends java.lang.Object
此类提供了一组断言方法,用于编写测试。只有失败的断言才会被记录。Assert 类的一些重要方法如下:
序号 | 方法和描述 |
---|---|
1 | void assertEquals(boolean expected, boolean actual) 检查两个基本类型/对象是否相等。 |
2 | void assertTrue(boolean condition) 检查条件是否为真。 |
3 | void assertFalse(boolean condition) 检查条件是否为假。 |
4 | void assertNotNull(Object object) 检查对象是否不为空。 |
5 | void assertNull(Object object) 检查对象是否为空。 |
6 | void assertSame(object1, object2) assertSame() 方法测试两个对象引用是否指向同一个对象。 |
7 | void assertNotSame(object1, object2) assertNotSame() 方法测试两个对象引用是否不指向同一个对象。 |
8 | void assertArrayEquals(expectedArray, resultArray); assertArrayEquals() 方法将测试两个数组是否彼此相等。 |
让我们在示例中使用上面提到的某些方法。在 **C:\>JUNIT_WORKSPACE** 中创建一个名为 **TestAssertions.java** 的 Java 类文件。
import org.junit.Test; import static org.junit.Assert.*; public class TestAssertions { @Test public void testAssertions() { //test data String str1 = new String ("abc"); String str2 = new String ("abc"); String str3 = null; String str4 = "abc"; String str5 = "abc"; int val1 = 5; int val2 = 6; String[] expectedArray = {"one", "two", "three"}; String[] resultArray = {"one", "two", "three"}; //Check that two objects are equal assertEquals(str1, str2); //Check that a condition is true assertTrue (val1 < val2); //Check that a condition is false assertFalse(val1 > val2); //Check that an object isn't null assertNotNull(str1); //Check that an object is null assertNull(str3); //Check if two object references point to the same object assertSame(str4,str5); //Check if two object references not point to the same object assertNotSame(str1,str3); //Check whether two arrays are equal to each other. assertArrayEquals(expectedArray, resultArray); } }
接下来,在 **C:\>JUNIT_WORKSPACE** 中创建一个名为 **TestRunner.java** 的 Java 类文件来执行测试用例。
import org.junit.runner.JUnitCore; import org.junit.runner.Result; import org.junit.runner.notification.Failure; public class TestRunner2 { public static void main(String[] args) { Result result = JUnitCore.runClasses(TestAssertions.class); for (Failure failure : result.getFailures()) { System.out.println(failure.toString()); } System.out.println(result.wasSuccessful()); } }
使用 javac 编译测试用例和测试运行器类。
C:\JUNIT_WORKSPACE>javac TestAssertions.java TestRunner.java
现在运行 Test Runner,它将运行在提供的测试用例类中定义的测试用例。
C:\JUNIT_WORKSPACE>java TestRunner
验证输出。
true
注解
注解就像可以添加到代码中的元标记,并将它们应用于方法或类中。JUnit 中的这些注解提供了有关测试方法的以下信息:
- 哪些方法将在测试方法之前和之后运行。
- 哪些方法在所有方法之前和之后运行,以及。
- 在执行期间将忽略哪些方法或类。
下表提供了 JUnit 中注解及其含义的列表:
序号 | 注解和描述 |
---|---|
1 | @Test Test 注解告诉 JUnit,附加到它的 public void 方法可以作为测试用例运行。 |
2 | @Before 几个测试需要在运行之前创建类似的对象。用 @Before 注解 public void 方法会导致在每个 Test 方法之前运行该方法。 |
3 | @After 如果在 Before 方法中分配外部资源,则需要在测试运行后释放它们。用 @After 注解 public void 方法会导致在 Test 方法之后运行该方法。 |
4 | @BeforeClass 用 @BeforeClass 注解 public static void 方法会导致在类中任何测试方法之前运行一次。 |
5 | @AfterClass 这将在所有测试完成后执行该方法。这可用于执行清理活动。 |
6 | @Ignore Ignore 注解用于忽略测试,并且该测试将不会执行。 |
在 **C:\>JUNIT_WORKSPACE** 中创建一个名为 **JunitAnnotation.java** 的 Java 类文件来测试注解。
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 JunitAnnotation { //execute before class @BeforeClass public static void beforeClass() { System.out.println("in before class"); } //execute after class @AfterClass public static void afterClass() { System.out.println("in after class"); } //execute before test @Before public void before() { System.out.println("in before"); } //execute after test @After public void after() { System.out.println("in after"); } //test case @Test public void test() { System.out.println("in test"); } //test case ignore and will not execute @Ignore public void ignoreTest() { System.out.println("in ignore test"); } }
接下来,在 **C:\>JUNIT_WORKSPACE** 中创建一个名为 **TestRunner.java** 的 Java 类文件来执行注解。
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(JunitAnnotation.class); for (Failure failure : result.getFailures()) { System.out.println(failure.toString()); } System.out.println(result.wasSuccessful()); } }
使用 javac 编译测试用例和测试运行器类。
C:\JUNIT_WORKSPACE>javac JunitAnnotation.java TestRunner.java
现在运行 Test Runner,它将运行在提供的测试用例类中定义的测试用例。
C:\JUNIT_WORKSPACE>java TestRunner
验证输出。
in before class in before in test in after in after class true
JUnit - 执行流程
本章解释了 JUnit 中方法的执行过程,该过程定义了调用的方法的顺序。下面讨论的是 JUnit 测试 API 方法的执行过程以及示例。
在 **C:\>JUNIT_WORKSPACE** 中创建一个名为 ExecutionProcedureJunit.java 的 Java 类文件来测试注解。
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 ExecutionProcedureJunit { //execute only once, in the starting @BeforeClass public static void beforeClass() { System.out.println("in before class"); } //execute only once, in the end @AfterClass public static void afterClass() { System.out.println("in after class"); } //execute for each test, before executing test @Before public void before() { System.out.println("in before"); } //execute for each test, after executing test @After public void after() { System.out.println("in after"); } //test case 1 @Test public void testCase1() { System.out.println("in test case 1"); } //test case 2 @Test public void testCase2() { System.out.println("in test case 2"); } }
接下来,在 **C:\>JUNIT_WORKSPACE** 中创建一个名为 **TestRunner.java** 的 Java 类文件来执行注解。
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(ExecutionProcedureJunit.class); for (Failure failure : result.getFailures()) { System.out.println(failure.toString()); } System.out.println(result.wasSuccessful()); } }
使用 javac 编译测试用例和测试运行器类。
C:\JUNIT_WORKSPACE>javac ExecutionProcedureJunit.java TestRunner.java
现在运行 Test Runner,它将运行在提供的测试用例类中定义的测试用例。
C:\JUNIT_WORKSPACE>java TestRunner
验证输出。
in before class in before in test case 1 in after in before in test case 2 in after in after class
请参阅上面的输出。执行过程如下:
- 首先,beforeClass() 方法只执行一次。
- afterClass() 方法只执行一次。
- before() 方法为每个测试用例执行,但在执行测试用例之前。
- after() 方法为每个测试用例执行,但在执行测试用例之后。
- 在 before() 和 after() 之间,每个测试用例都会执行。
JUnit - 执行测试
测试用例使用 **JUnitCore** 类执行。JUnitCore 是用于运行测试的 facade。它支持运行 JUnit 4 测试、JUnit 3.8.x 测试以及混合测试。要从命令行运行测试,请运行 java org.junit.runner.JUnitCore
以下是 **org.junit.runner.JUnitCore** 类的声明
public class JUnitCore extends java.lang.Object
在这里,我们将看到如何借助 JUnitCore 执行测试。
创建类
创建一个要测试的 Java 类,例如 **MessageUtil.java**,在 **C:\>JUNIT_WORKSPACE** 中。
/* * This class prints the given message on console. */ public class MessageUtil { private String message; //Constructor //@param message to be printed public MessageUtil(String message){ this.message = message; } // prints the message public String printMessage(){ System.out.println(message); return message; } }
创建测试用例类
创建一个 Java 测试类,例如,TestJunit.java。
向您的测试类添加一个测试方法 testPrintMessage()。
向 testPrintMessage() 方法添加注解 @Test。
实现测试条件并使用 JUnit 的 assertEquals API 检查条件。
在 **C:\>JUNIT_WORKSPACE** 中创建一个名为 **TestJunit.java** 的 Java 类文件。
import org.junit.Test; import static org.junit.Assert.assertEquals; public class TestJunit { String message = "Hello World"; MessageUtil messageUtil = new MessageUtil(message); @Test public void testPrintMessage() { assertEquals(message,messageUtil.printMessage()); } }
创建测试运行器类
现在在 **C:\>JUNIT_WORKSPACE** 中创建一个名为 **TestRunner.java** 的 Java 类文件来执行测试用例。它导入 JUnitCore 类并使用 runClasses() 方法,该方法将测试类名作为其参数。
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(TestJunit.class); for (Failure failure : result.getFailures()) { System.out.println(failure.toString()); } System.out.println(result.wasSuccessful()); } }
使用 javac 编译测试用例和测试运行器类。
C:\JUNIT_WORKSPACE>javac MessageUtil.java TestJunit.java TestRunner.java
现在运行 Test Runner,它将运行在提供的测试用例类中定义的测试用例。
C:\JUNIT_WORKSPACE>java TestRunner
验证输出。
Hello World true
JUnit - 套件测试
**测试套件** 用于捆绑一些单元测试用例并一起运行它们。在 JUnit 中,@RunWith 和 @Suite 注解都用于运行套件测试。本章以一个包含两个测试类 TestJunit1 和 TestJunit2 的示例为例,它们使用测试套件一起运行。
创建类
在 **C:\>JUNIT_WORKSPACE** 中创建一个要测试的 Java 类,例如 **MessageUtil.java**。
/* * This class prints the given message on console. */ public class MessageUtil { private String message; //Constructor //@param message to be printed public MessageUtil(String message){ this.message = message; } // prints the message public String printMessage(){ System.out.println(message); return message; } // add "Hi!" to the message public String salutationMessage(){ message = "Hi!" + message; System.out.println(message); return message; } }
创建测试用例类
在 **C:\>JUNIT_WORKSPACE** 中创建一个名为 **TestJunit1.java** 的 Java 类文件。
import org.junit.Test; import org.junit.Ignore; import static org.junit.Assert.assertEquals; public class TestJunit1 { String message = "Robert"; MessageUtil messageUtil = new MessageUtil(message); @Test public void testPrintMessage() { System.out.println("Inside testPrintMessage()"); assertEquals(message, messageUtil.printMessage()); } }
在 **C:\>JUNIT_WORKSPACE** 中创建一个名为 **TestJunit2.java** 的 Java 类文件。
import org.junit.Test; import org.junit.Ignore; import static org.junit.Assert.assertEquals; public class TestJunit2 { String message = "Robert"; MessageUtil messageUtil = new MessageUtil(message); @Test public void testSalutationMessage() { System.out.println("Inside testSalutationMessage()"); message = "Hi!" + "Robert"; assertEquals(message,messageUtil.salutationMessage()); } }
创建测试套件类
- 创建一个 Java 类。
- 使用 @RunWith(Suite.class) 注解附加到该类。
- 使用 @Suite.SuiteClasses 注解添加对 JUnit 测试类的引用。
在 **C:\>JUNIT_WORKSPACE** 中创建一个名为 **TestSuite.java** 的 Java 类文件来执行测试用例。
import org.junit.runner.RunWith; import org.junit.runners.Suite; @RunWith(Suite.class) @Suite.SuiteClasses({ TestJunit1.class, TestJunit2.class }) public class JunitTestSuite { }
创建测试运行器类
在 **C:\>JUNIT_WORKSPACE** 中创建一个名为 **TestRunner.java** 的 Java 类文件来执行测试用例。
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(JunitTestSuite.class); for (Failure failure : result.getFailures()) { System.out.println(failure.toString()); } System.out.println(result.wasSuccessful()); } }
使用 javac 编译所有 Java 类。
C:\JUNIT_WORKSPACE>javac MessageUtil.java TestJunit1.java TestJunit2.java JunitTestSuite.java TestRunner.java
现在运行 Test Runner,它将运行在提供的测试用例类中定义的测试用例。
C:\JUNIT_WORKSPACE>java TestRunner
验证输出。
Inside testPrintMessage() Robert Inside testSalutationMessage() Hi Robert true
JUnit - 忽略测试
有时我们的代码在运行测试用例时并非完全准备好,导致测试用例失败。在这种情况下,@Ignore 注解很有帮助。
用 @Ignore 注解的测试方法不会被执行。
如果一个测试类用 @Ignore 注解,那么它的所有测试方法都不会被执行。
现在让我们看看 @Ignore 的实际应用。
创建类
在 **C:\>JUNIT_WORKSPACE** 中创建一个要测试的 Java 类,例如 **MessageUtil.java**。
/* * This class prints the given message on console. */ public class MessageUtil { private String message; //Constructor //@param message to be printed public MessageUtil(String message){ this.message = message; } // prints the message public String printMessage(){ System.out.println(message); return message; } // add "Hi!" to the message public String salutationMessage(){ message = "Hi!" + message; System.out.println(message); return message; } }
创建测试用例类
创建一个 Java 测试类,例如,TestJunit.java。
在你的测试类中添加一个测试方法 testPrintMessage() 或 testSalutationMessage()。
在 testPrintMessage() 方法中添加 @Ignore 注解。
在 C:\JUNIT_WORKSPACE 中创建一个名为 TestJunit.java 的 Java 类文件。
import org.junit.Test; import org.junit.Ignore; import static org.junit.Assert.assertEquals; public class TestJunit { String message = "Robert"; MessageUtil messageUtil = new MessageUtil(message); @Ignore @Test public void testPrintMessage() { System.out.println("Inside testPrintMessage()"); message = "Robert"; assertEquals(message,messageUtil.printMessage()); } @Test public void testSalutationMessage() { System.out.println("Inside testSalutationMessage()"); message = "Hi!" + "Robert"; assertEquals(message,messageUtil.salutationMessage()); } }
创建测试运行器类
在 **C:\>JUNIT_WORKSPACE** 中创建一个名为 **TestRunner.java** 的 Java 类文件来执行测试用例。
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(TestJunit.class); for (Failure failure : result.getFailures()) { System.out.println(failure.toString()); } System.out.println(result.wasSuccessful()); } }
使用 javac 编译 MessageUtil、测试用例和测试运行器类。
C:\JUNIT_WORKSPACE>javac MessageUtil.java TestJunit.java TestRunner.java
现在运行测试运行器,它不会运行在提供的测试用例类中定义的 testPrintMessage() 测试用例。
C:\JUNIT_WORKSPACE>java TestRunner
验证输出。testPrintMessage() 测试用例未被测试。
Inside testSalutationMessage() Hi!Robert true
现在,更新 C:\JUNIT_WORKSPACE 中的 TestJunit 以忽略所有测试用例。在类级别添加 @Ignore。
import org.junit.Test; import org.junit.Ignore; import static org.junit.Assert.assertEquals; @Ignore public class TestJunit { String message = "Robert"; MessageUtil messageUtil = new MessageUtil(message); @Test public void testPrintMessage() { System.out.println("Inside testPrintMessage()"); message = "Robert"; assertEquals(message,messageUtil.printMessage()); } @Test public void testSalutationMessage() { System.out.println("Inside testSalutationMessage()"); message = "Hi!" + "Robert"; assertEquals(message,messageUtil.salutationMessage()); } }
使用 javac 编译测试用例。
C:\JUNIT_WORKSPACE>javac TestJunit.java
保持你的测试运行器不变,如下所示:
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(TestJunit.class); for (Failure failure : result.getFailures()) { System.out.println(failure.toString()); } System.out.println(result.wasSuccessful()); } }
现在运行测试运行器,它不会运行在提供的测试用例类中定义的任何测试用例。
C:\JUNIT_WORKSPACE>java TestRunner
验证输出。没有任何测试用例被测试。
true
JUnit - 时间测试
JUnit 提供了一个方便的超时选项。如果测试用例花费的时间超过指定的毫秒数,JUnit 将自动将其标记为失败。timeout 参数与 @Test 注解一起使用。让我们看看 @Test(timeout) 的实际应用。
创建类
在 **C:\>JUNIT_WORKSPACE** 中创建一个要测试的 Java 类,例如 **MessageUtil.java**。
在 printMessage() 方法内添加一个无限 while 循环。
/* * This class prints the given message on console. */ public class MessageUtil { private String message; //Constructor //@param message to be printed public MessageUtil(String message){ this.message = message; } // prints the message public void printMessage(){ System.out.println(message); while(true); } // add "Hi!" to the message public String salutationMessage(){ message = "Hi!" + message; System.out.println(message); return message; } }
创建测试用例类
创建一个 Java 测试类,例如 TestJunit.java。为 testPrintMessage() 测试用例添加 1000 的超时时间。
在 **C:\>JUNIT_WORKSPACE** 中创建一个名为 **TestJunit.java** 的 Java 类文件。
import org.junit.Test; import org.junit.Ignore; import static org.junit.Assert.assertEquals; public class TestJunit { String message = "Robert"; MessageUtil messageUtil = new MessageUtil(message); @Test(timeout = 1000) public void testPrintMessage() { System.out.println("Inside testPrintMessage()"); messageUtil.printMessage(); } @Test public void testSalutationMessage() { System.out.println("Inside testSalutationMessage()"); message = "Hi!" + "Robert"; assertEquals(message,messageUtil.salutationMessage()); } }
创建测试运行器类
在 **C:\>JUNIT_WORKSPACE** 中创建一个名为 **TestRunner.java** 的 Java 类文件来执行测试用例。
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(TestJunit.class); for (Failure failure : result.getFailures()) { System.out.println(failure.toString()); } System.out.println(result.wasSuccessful()); } }
使用 javac 编译 MessageUtil、测试用例和测试运行器类。
C:\JUNIT_WORKSPACE>javac MessageUtil.java TestJunit.java TestRunner.java
现在运行测试运行器,它将运行在提供的测试用例类中定义的测试用例。
C:\JUNIT_WORKSPACE>java TestRunner
验证输出。testPrintMessage() 测试用例将标记单元测试失败。
Inside testPrintMessage() Robert Inside testSalutationMessage() Hi!Robert testPrintMessage(TestJunit): test timed out after 1000 milliseconds false
JUnit - 异常测试
JUnit 提供了跟踪代码异常处理的选项。你可以测试代码是否抛出了所需的异常。expected 参数与 @Test 注解一起使用。让我们看看 @Test(expected) 的实际应用。
创建类
创建一个要测试的 Java 类,例如 MessageUtil.java,位于 C:\JUNIT_WORKSPACE。
在 printMessage() 方法中添加一个错误条件。
/* * This class prints the given message on console. */ public class MessageUtil { private String message; //Constructor //@param message to be printed public MessageUtil(String message){ this.message = message; } // prints the message public void printMessage(){ System.out.println(message); int a = 0; int b = 1/a; } // add "Hi!" to the message public String salutationMessage(){ message = "Hi!" + message; System.out.println(message); return message; } }
创建测试用例类
创建一个名为 TestJunit.java 的 Java 测试类。在 testPrintMessage() 测试用例中添加预期的异常 ArithmeticException。
在 **C:\>JUNIT_WORKSPACE** 中创建一个名为 **TestJunit.java** 的 Java 类文件。
import org.junit.Test; import org.junit.Ignore; import static org.junit.Assert.assertEquals; public class TestJunit { String message = "Robert"; MessageUtil messageUtil = new MessageUtil(message); @Test(expected = ArithmeticException.class) public void testPrintMessage() { System.out.println("Inside testPrintMessage()"); messageUtil.printMessage(); } @Test public void testSalutationMessage() { System.out.println("Inside testSalutationMessage()"); message = "Hi!" + "Robert"; assertEquals(message,messageUtil.salutationMessage()); } }
创建测试运行器类
在 **C:\>JUNIT_WORKSPACE** 中创建一个名为 **TestRunner.java** 的 Java 类文件来执行测试用例。
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(TestJunit.class); for (Failure failure : result.getFailures()) { System.out.println(failure.toString()); } System.out.println(result.wasSuccessful()); } }
使用 javac 编译 MessageUtil、测试用例和测试运行器类。
C:\JUNIT_WORKSPACE>javac MessageUtil.java TestJunit.java TestRunner.java
现在运行测试运行器,它将运行在提供的测试用例类中定义的测试用例。
C:\JUNIT_WORKSPACE>java TestRunner
验证输出。testPrintMessage() 测试用例将通过。
Inside testPrintMessage() Robert Inside testSalutationMessage() Hi!Robert true
JUnit - 参数化测试
JUnit 4 引入了一项名为 参数化测试 的新功能。参数化测试允许开发人员使用不同的值反复运行相同的测试。创建参数化测试需要遵循五个步骤。
使用 @RunWith(Parameterized.class) 注解测试类。
创建一个用 @Parameters 注解的公共静态方法,该方法返回一个对象集合(作为数组)作为测试数据集。
创建一个公共构造函数,它接收相当于测试数据的一“行”。
为测试数据的每一“列”创建一个实例变量。
使用实例变量作为测试数据的来源创建测试用例。
对于数据的每一行,测试用例都将被调用一次。让我们看看参数化测试的实际应用。
创建类
创建一个要测试的 Java 类,例如 PrimeNumberChecker.java,位于 C:\JUNIT_WORKSPACE。
public class PrimeNumberChecker { public Boolean validate(final Integer primeNumber) { for (int i = 2; i < (primeNumber / 2); i++) { if (primeNumber % i == 0) { return false; } } return true; } }
创建参数化测试用例类
创建一个 Java 测试类,例如 PrimeNumberCheckerTest.java。在 C:\JUNIT_WORKSPACE 中创建一个名为 PrimeNumberCheckerTest.java 的 Java 类文件。
import java.util.Arrays; import java.util.Collection; import org.junit.Test; import org.junit.Before; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; import org.junit.runner.RunWith; import static org.junit.Assert.assertEquals; @RunWith(Parameterized.class) public class PrimeNumberCheckerTest { private Integer inputNumber; private Boolean expectedResult; private PrimeNumberChecker primeNumberChecker; @Before public void initialize() { primeNumberChecker = new PrimeNumberChecker(); } // Each parameter should be placed as an argument here // Every time runner triggers, it will pass the arguments // from parameters we defined in primeNumbers() method public PrimeNumberCheckerTest(Integer inputNumber, Boolean expectedResult) { this.inputNumber = inputNumber; this.expectedResult = expectedResult; } @Parameterized.Parameters public static Collection primeNumbers() { return Arrays.asList(new Object[][] { { 2, true }, { 6, false }, { 19, true }, { 22, false }, { 23, true } }); } // This test will run 4 times since we have 5 parameters defined @Test public void testPrimeNumberChecker() { System.out.println("Parameterized Number is : " + inputNumber); assertEquals(expectedResult, primeNumberChecker.validate(inputNumber)); } }
创建测试运行器类
在 **C:\>JUNIT_WORKSPACE** 中创建一个名为 **TestRunner.java** 的 Java 类文件来执行测试用例。
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(PrimeNumberCheckerTest.class); for (Failure failure : result.getFailures()) { System.out.println(failure.toString()); } System.out.println(result.wasSuccessful()); } }
使用 javac 编译 PrimeNumberChecker、PrimeNumberCheckerTest 和测试运行器类。
C:\JUNIT_WORKSPACE>javac PrimeNumberChecker.java PrimeNumberCheckerTest.java TestRunner.java
现在运行测试运行器,它将运行在提供的测试用例类中定义的测试用例。
C:\JUNIT_WORKSPACE>java TestRunner
验证输出。
Parameterized Number is : 2 Parameterized Number is : 6 Parameterized Number is : 19 Parameterized Number is : 22 Parameterized Number is : 23 true
JUnit - 与 Ant 集成
我们将通过一个示例演示如何使用 Ant 运行 JUnit。请按照以下步骤操作。
步骤 1:下载 Apache Ant
根据你正在使用的操作系统下载 Apache Ant。
操作系统 | 归档名称 |
---|---|
Windows | apache-ant-1.8.4-bin.zip |
Linux | apache-ant-1.8.4-bin.tar.gz |
Mac | apache-ant-1.8.4-bin.tar.gz |
步骤 2:设置 Ant 环境
设置 ANT_HOME 环境变量,使其指向 ANT 库存储在你机器上的基目录位置。假设 Ant 库存储在 apache-ant-1.8.4 文件夹中。
序号 | 操作系统和说明 |
---|---|
1 | Windows 将环境变量 ANT_HOME 设置为 C:\Program Files\Apache Software Foundation\apache-ant-1.8.4 |
2 | Linux export ANT_HOME = /usr/local/apache-ant-1.8.4 |
3 | Mac export ANT_HOME = /Library/apache-ant-1.8.4 |
将 Ant 编译器位置追加到系统路径,如下所示:
操作系统 | 输出 |
---|---|
Windows | 在系统变量 Path 的末尾追加字符串 %ANT_HOME\bin。 |
Linux | export PATH = $PATH:$ANT_HOME/bin/ |
Mac | 不需要 |
步骤 3:下载 JUnit 归档文件
下载适合你操作系统的 JUnit 归档文件。
操作系统 | 归档名称 |
---|---|
Windows | junit4.10.jar |
Linux | junit4.10.jar |
Mac | junit4.10.jar |
步骤 4:创建项目结构
在 C:\JUNIT_WORKSPACE 中创建一个名为 TestJunitWithAnt 的文件夹。
在 C:\JUNIT_WORKSPACE\TestJunitWithAnt 中创建一个名为 src 的文件夹。
在 C:\JUNIT_WORKSPACE\TestJunitWithAnt 中创建一个名为 test 的文件夹。
在 C:\JUNIT_WORKSPACE\TestJunitWithAnt 中创建一个名为 lib 的文件夹。
在 C:\JUNIT_WORKSPACE\TestJunitWithAnt\src 文件夹中创建 MessageUtil 类。
/* * This class prints the given message on console. */ public class MessageUtil { private String message; //Constructor //@param message to be printed public MessageUtil(String message){ this.message = message; } // prints the message public String printMessage(){ System.out.println(message); return message; } // add "Hi!" to the message public String salutationMessage(){ message = "Hi!" + message; System.out.println(message); return message; } }
在 C:\JUNIT_WORKSPACE\TestJunitWithAnt\src 文件夹中创建 TestMessageUtil 类。
import org.junit.Test; import org.junit.Ignore; import static org.junit.Assert.assertEquals; public class TestMessageUtil { String message = "Robert"; MessageUtil messageUtil = new MessageUtil(message); @Test public void testPrintMessage() { System.out.println("Inside testPrintMessage()"); assertEquals(message,messageUtil.printMessage()); } @Test public void testSalutationMessage() { System.out.println("Inside testSalutationMessage()"); message = "Hi!" + "Robert"; assertEquals(message,messageUtil.salutationMessage()); } }
将 junit-4.10.jar 复制到 C:\JUNIT_WORKSPACE\TestJunitWithAnt\lib 文件夹。
创建 Ant Build.xml
我们将使用 Ant 中的 <junit> 任务来执行我们的 JUnit 测试用例。
<project name = "JunitTest" default = "test" basedir = "."> <property name = "testdir" location = "test" /> <property name = "srcdir" location = "src" /> <property name = "full-compile" value = "true" /> <path id = "classpath.base"/> <path id = "classpath.test"> <pathelement location = "lib/junit-4.10.jar" /> <pathelement location = "${testdir}" /> <pathelement location = "${srcdir}" /> <path refid = "classpath.base" /> </path> <target name = "clean" > <delete verbose = "${full-compile}"> <fileset dir = "${testdir}" includes = "**/*.class" /> </delete> </target> <target name = "compile" depends = "clean"> <javac srcdir = "${srcdir}" destdir = "${testdir}" verbose = "${full-compile}"> <classpath refid = "classpath.test"/> </javac> </target> <target name = "test" depends = "compile"> <junit> <classpath refid = "classpath.test" /> <formatter type = "brief" usefile = "false" /> <test name = "TestMessageUtil" /> </junit> </target> </project>
运行以下 Ant 命令。
C:\JUNIT_WORKSPACE\TestJunitWithAnt>ant
验证输出。
Buildfile: C:\JUNIT_WORKSPACE\TestJunitWithAnt\build.xml clean: compile: [javac] Compiling 2 source files to C:\JUNIT_WORKSPACE\TestJunitWithAnt\test [javac] [parsing started C:\JUNIT_WORKSPACE\TestJunitWithAnt\src\ MessageUtil.java] [javac] [parsing completed 18ms] [javac] [parsing started C:\JUNIT_WORKSPACE\TestJunitWithAnt\src\ TestMessageUtil.java] [javac] [parsing completed 2ms] [javac] [search path for source files: C:\JUNIT_WORKSPACE\ TestJunitWithAnt\src] [javac] [loading java\lang\Object.class(java\lang:Object.class)] [javac] [loading java\lang\String.class(java\lang:String.class)] [javac] [loading org\junit\Test.class(org\junit:Test.class)] [javac] [loading org\junit\Ignore.class(org\junit:Ignore.class)] [javac] [loading org\junit\Assert.class(org\junit:Assert.class)] [javac] [loading java\lang\annotation\Retention.class (java\lang\annotation:Retention.class)] [javac] [loading java\lang\annotation\RetentionPolicy.class (java\lang\annotation:RetentionPolicy.class)] [javac] [loading java\lang\annotation\Target.class (java\lang\annotation:Target.class)] [javac] [loading java\lang\annotation\ElementType.class (java\lang\annotation:ElementType.class)] [javac] [loading java\lang\annotation\Annotation.class (java\lang\annotation:Annotation.class)] [javac] [checking MessageUtil] [javac] [loading java\lang\System.class(java\lang:System.class)] [javac] [loading java\io\PrintStream.class(java\io:PrintStream.class)] [javac] [loading java\io\FilterOutputStream.class (java\io:FilterOutputStream.class)] [javac] [loading java\io\OutputStream.class(java\io:OutputStream.class)] [javac] [loading java\lang\StringBuilder.class (java\lang:StringBuilder.class)] [javac] [loading java\lang\AbstractStringBuilder.class (java\lang:AbstractStringBuilder.class)] [javac] [loading java\lang\CharSequence.class(java\lang:CharSequence.class)] [javac] [loading java\io\Serializable.class(java\io:Serializable.class)] [javac] [loading java\lang\Comparable.class(java\lang:Comparable.class)] [javac] [loading java\lang\StringBuffer.class(java\lang:StringBuffer.class)] [javac] [wrote C:\JUNIT_WORKSPACE\TestJunitWithAnt\test\MessageUtil.class] [javac] [checking TestMessageUtil] [javac] [wrote C:\JUNIT_WORKSPACE\TestJunitWithAnt\test\TestMessageUtil.class] [javac] [total 281ms] test: [junit] Testsuite: TestMessageUtil [junit] Tests run: 2, Failures: 0, Errors: 0, Time elapsed: 0.008 sec [junit] [junit] ------------- Standard Output --------------- [junit] Inside testPrintMessage() [junit] Robert [junit] Inside testSalutationMessage() [junit] Hi!Robert [junit] ------------- ---------------- --------------- BUILD SUCCESSFUL Total time: 0 seconds
JUnit - 与 Eclipse 集成
要使用 Eclipse 设置 JUnit,请按照以下步骤操作。
步骤 1:下载 JUnit 归档文件
根据你系统上的操作系统下载 JUnit jar 文件。
操作系统 | 归档名称 |
---|---|
Windows | junit4.10.jar |
Linux | junit4.10.jar |
Mac | junit4.10.jar |
假设你已将上述 JAR 文件复制到 C:\JUnit 文件夹。
步骤 2:设置 Eclipse 环境
打开 Eclipse → 右键单击项目并单击属性 → 构建路径 → 配置构建路径,并使用“添加外部 Jar”按钮在库中添加 junit-4.10.jar。
我们假设你的 Eclipse 具有内置的 JUnit 插件。如果它不存在于 C:\eclipse\plugins 目录中,你可以从 JUnit Plugin 下载它。将下载的 zip 文件解压缩到 Eclipse 的 plugin 文件夹中。最后重新启动 Eclipse。
现在你的 Eclipse 已准备好开发 JUnit 测试用例。
步骤 3:验证 Eclipse 中的 JUnit 安装
在任何位置的 Eclipse 中创建一个名为 TestJunit 的项目。然后在项目中创建一个要测试的 MessageUtil 类。
/* * This class prints the given message on console. */ public class MessageUtil { private String message; //Constructor //@param message to be printed public MessageUtil(String message){ this.message = message; } // prints the message public String printMessage(){ System.out.println(message); return message; } }
在项目中创建一个测试类 TestJunit。
import org.junit.Test; import static org.junit.Assert.assertEquals; public class TestJunit { String message = "Hello World"; MessageUtil messageUtil = new MessageUtil(message); @Test public void testPrintMessage() { assertEquals(message,messageUtil.printMessage()); } }
项目结构应如下所示:
最后,右键单击程序并选择“以 JUnit 运行”以验证程序的输出。
验证结果。
JUnit - 扩展
以下是 JUnit 扩展:
- Cactus
- JWebUnit
- XMLUnit
- MockObject
Cactus
Cactus 是一个简单的测试框架,用于单元测试服务器端 Java 代码(Servlet、EJB、标签库、过滤器)。Cactus 的目的是降低编写服务器端代码测试的成本。它使用 JUnit 并对其进行扩展。Cactus 实现了一个容器内策略,该策略在容器内执行测试。
Cactus 生态系统由多个组件组成:
Cactus 框架是 Cactus 的核心。它是提供编写 Cactus 测试的 API 的引擎。
Cactus 集成模块是前端和框架,它们提供了使用 Cactus 框架的简便方法(Ant 脚本、Eclipse 插件和 Maven 插件)。
以下代码演示了如何使用 Cactus。
import org.apache.cactus.*; import junit.framework.*; public class TestSampleServlet extends ServletTestCase { @Test public void testServlet() { // Initialize class to test SampleServlet servlet = new SampleServlet(); // Set a variable in session as the doSomething() // method that we are testing session.setAttribute("name", "value"); // Call the method to test, passing an // HttpServletRequest object (for example) String result = servlet.doSomething(request); // Perform verification that test was successful assertEquals("something", result); assertEquals("otherValue", session.getAttribute("otherName")); } }
JWebUnit
JWebUnit 是一个基于 Java 的 Web 应用程序测试框架。它使用统一的简单测试接口包装现有的测试框架(如 HtmlUnit 和 Selenium),以测试 Web 应用程序的正确性。
JWebUnit 提供了一个高级 Java API,用于导航 Web 应用程序,并结合一系列断言来验证应用程序的正确性。这包括通过链接导航、表单输入和提交、表内容验证以及其他典型的业务 Web 应用程序功能。
简单的导航方法和现成的断言允许比仅使用 JUnit 或 HtmlUnit 更快地创建测试。如果你想从 HtmlUnit 切换到其他插件,例如 Selenium(即将推出),则无需重写你的测试。
这是一个示例代码。
import junit.framework.TestCase; import net.sourceforge.jwebunit.WebTester; public class ExampleWebTestCase extends TestCase { private WebTester tester; public ExampleWebTestCase(String name) { super(name); tester = new WebTester(); } //set base url public void setUp() throws Exception { getTestContext().setBaseUrl("http://myserver:8080/myapp"); } // test base info @Test public void testInfoPage() { beginAt("/info.html"); } }
XMLUnit
XMLUnit 提供单个 JUnit 扩展类 XMLTestCase 和一组支持类,允许对以下内容进行断言:
两段 XML 之间的差异(通过 Diff 和 DetailedDiff 类)。
XML 片段的有效性(通过 Validator 类)。
使用 XSLT 转换 XML 片段的结果(通过 Transform 类)。
在 XML 片段上评估 XPath 表达式的结果(通过实现 XpathEngine 接口的类)。
通过 DOM 遍历公开的 XML 片段中的各个节点(通过 NodeTest 类)。
让我们假设我们有两段 XML 需要比较并断言它们相等。我们可以编写一个简单的测试类,如下所示:
import org.custommonkey.xmlunit.XMLTestCase; public class MyXMLTestCase extends XMLTestCase { // this test method compare two pieces of the XML @Test public void testForXMLEquality() throws Exception { String myControlXML = "<msg><uuid>0x00435A8C</uuid></msg>"; String myTestXML = "<msg><localId>2376</localId></msg>"; assertXMLEqual("Comparing test xml to control xml", myControlXML, myTestXML); } }
MockObject
在单元测试中,模拟对象可以模拟复杂、真实的(非模拟)对象的 behavior,因此当在单元测试中包含真实对象不切实际或不可能时,它们非常有用。
使用模拟对象进行测试的常见编码风格是:
- 创建模拟对象的实例。
- 在模拟对象中设置状态和期望。
- 使用模拟对象作为参数调用领域代码。
- 验证模拟对象的一致性。
以下是使用 Jmock 的 MockObject 示例。
import org.jmock.Mockery; import org.jmock.Expectations; class PubTest extends TestCase { Mockery context = new Mockery(); public void testSubReceivesMessage() { // set up final Sub sub = context.mock(Sub.class); Pub pub = new Pub(); pub.add(sub); final String message = "message"; // expectations context.checking(new Expectations() { oneOf (sub).receive(message); }); // execute pub.publish(message); // verify context.assertIsSatisfied(); } }