使用 Maven 和 IntelliJ 使用 JUnit 进行单元测试 - 第 1 部分

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡/ 赠书活动

目前,正在 星球 内带小伙伴们做第一个项目:全栈前后端分离博客项目,采用技术栈 Spring Boot + Mybatis Plus + Vue 3.x + Vite 4手把手,前端 + 后端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,陪伴式直到项目上线,目前已更新了 204 小节,累计 32w+ 字,讲解图:1416 张,还在持续爆肝中,后续还会上新更多项目,目标是将 Java 领域典型的项目都整上,如秒杀系统、在线商城、IM 即时通讯、权限管理等等,已有 870+ 小伙伴加入,欢迎点击围观

单元测试是 测试软件 的第一级,您可以在其中编写测试代码来执行要测试的代码中的特定功能。在大多数情况下,作为程序员,您有责任交付经过单元测试的代码。目的是检查软件单元(例如被测类的公共方法)是否按预期运行和/或返回预期数据。单元测试 不是 在生产系统上进行的,而是作为独立的单元进行的。如果被测单元具有外部依赖性,例如外部数据源或 Web 服务,则依赖性将替换为测试实现或使用测试框架创建的模拟对象。单元测试不是唯一的类型,它本身无法处理所有测试方面。其他类型的测试,例如集成和功能测试,在测试软件中有其自身的作用。

在本系列文章中,我们将重点介绍使用 JUnit 进行单元测试——JUnit 是最流行的 Java 代码测试框架之一。在这篇文章中,我们将从创建和执行基本单元测试开始,然后在后续文章中转向特定的单元测试方面。

核心 JUnit 框架包含在一个 JAR 文件中,您可以下载该文件,将类路径指向它,然后创建和运行测试。但在这篇文章中,我们将学习如何以真正的程序员的方式执行单元测试。我们将从 Maven 开始,然后转向 IntelliJ。

使用 Maven 进行单元测试

您可能听说过 Maven 被称为构建工具。但是,除了从源代码构建可部署工件的能力之外,Maven 还提供了许多用于管理软件开发生命周期的特性。单元测试就是这样一种功能,它作为测试阶段合并到 Maven 构建生命周期 中。

在不深入研究 Maven 的情况下,让我们开始使用 Maven 进行第一个 JUnit 测试。

    1. 下载并安装 Maven (如果尚未完成)。
    2. 打开命令提示符 (Windows) 或终端(*uix 或 Mac),浏览到工作目录以设置项目,然后执行以下命令。

 mvn archetype:generate -DgroupId=guru.springframework.unittest.quickstart -DartifactId=unittest -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false


前面的 archetype:generate 命令使用 maven-archetype-quickstart 模板创建一个基本的 Maven 项目,该项目包含一个 pom.xml 文件、一个 App.java 类和一个 AppTest.java 测试类,目录结构如下。


 mvn archetype:generate -DgroupId=guru.springframework.unittest.quickstart -DartifactId=unittest -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false


在上面的目录结构中, pom.xml 文件,也称为 Maven 配置文件,是 Maven 项目的核心。它是您定义项目配置的地方——特别是项目的依赖项。例如,由于我们的项目依赖于 JUnit,因此我们需要在 pom.xml 文件中将其声明为依赖项。尽管默认情况下 JUnit 依赖项已经存在,但我们将更新它以指向最新的 JUnit 版本。这就是我们最终的 pom.xml 文件的样子。

pom.xml:


 mvn archetype:generate -DgroupId=guru.springframework.unittest.quickstart -DartifactId=unittest -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false


现在我们已经设置了一个基本的 Java 类、一个测试类和 pom.xml 配置,我们可以运行单元测试了。

    1. 从工作目录执行 mvn test 命令。

此命令将运行 Maven 为我们生成的默认 AppTest 类,输出如下。


 mvn archetype:generate -DgroupId=guru.springframework.unittest.quickstart -DartifactId=unittest -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

我们已经使用 Maven 执行了 JUnit 测试。该测试通过了,但几乎没有提供任何价值。接下来,我们将使用 IntelliJ IDE 编写和执行更全面的测试。

IntelliJ 中的单元测试

使用 IntelliJ,您可以轻松创建、运行和调试单元测试。在其他几个单元测试框架中,IntelliJ 提供了对 JUnit 的内置支持。在 IntelliJ 中,您可以通过单击创建 JUnit 测试类,并在测试类及其对应的目标类之间快速导航以调试测试错误。 IntelliJ 中一个非常有用的单元测试功能是代码覆盖率。使用此功能,您可以查看项目中单元测试覆盖的方法甚至代码行的确切百分比。

让我们将现有的 Maven 项目导入 IntelliJ 并进行一些单元测试。

将 Maven 项目导入 IntelliJ

如果您没有安装 IntelliJ,请从 官方网站 下载并安装免费的社区版或终极版的 30 天试用版。完成后,执行以下步骤:

    1. 打开 IntelliJ。
    2. “欢迎使用 IntelliJ IDEA” 窗口中,单击 “导入项目”

    1. “选择要导入的文件或目录” 对话框中,浏览到 Maven 项目的工作目录并选择 pom.xml 文件。

    1. 单击 确定 按钮。
    2. 在出现的 Import Project from Maven 对话框中,选中 Import Maven projects automatically 复选框以在每次 pom.xml 文件更改时同步 Maven 和 InteliiJ 项目之间的更改。

    1. 通过几个对话框单击 Next 按钮,接受默认设置,最后单击 Finish 。 IntelliJ 的 项目 窗口显示项目结构。

  1. 双击 项目 窗口中的 App 以在代码编辑器中将其打开。
  2. 用这段代码替换 App 类的默认代码。

应用程序.java:


 mvn archetype:generate -DgroupId=guru.springframework.unittest.quickstart -DartifactId=unittest -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false


在上面的代码中,我们在 App 类中编写了一个 concatAndConvertString() 方法,它接受两个 String 参数。该方法首先连接字符串并将结果转换为大写,然后再返回。

接下来我们将添加一个测试类来测试 concatAndConvertString() 方法。

添加测试类

让我们从头开始完成在 IntelliJ 中添加测试类的步骤。

    1. 项目 窗口中删除默认的 AppTest 类。
    2. Project 窗口中,在 main 下创建一个名为 test 的 目录,我们将使用 test 目录将测试代码与应用程序代码分开。
    3. 右键单击 test 并选择 Mark Directory As→Test Sources Root

    1. App 类打开的代码编辑器中,按 Shift+F10 并选择 Create New Test

    1. 在出现的 Create Test 对话框中,选择 jUnit4 单选按钮和对应于我们将测试的 concatAndConvertString() 方法的复选框。

  1. 单击 确定 按钮。 JUnit 使用用 @Test 注释修饰的 testConcatAndConvertString() 方法创建 AppTest 类。此注释告诉 JUnit 将该方法作为测试用例运行。在测试方法中,我们将编写代码来测试 App concatAndConvertString() 方法。

AppTest.Java:


 mvn archetype:generate -DgroupId=guru.springframework.unittest.quickstart -DartifactId=unittest -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false


在上面示例的第 12 行中,我们调用了 assertEquals() 方法,这是几种 JUnit 断言方法之一。此重载方法检查两个 String 对象是否相等。如果不是,该方法将抛出一个 AssertionError 。在我们的示例中,我们通过将预期的字符串值 ( HELLOWORLD ) 作为第一个参数传递并将 concatAndConvertString() 方法返回的实际值作为第二个参数传递来调用 assertEquals() 方法。

运行单元测试

要运行测试,请从 IntelliJ 的“运行”菜单中选择 “运行 AppTest” 或按 Shift+F10 运行 窗口显示测试结果。绿色突出显示框表示测试已完成且没有任何失败。

要了解如何报告测试失败,请将 expectedValue 变量的值更改为 HelloWorld 并按 Shift+F10 “运行” 对话框显示红色进度条以指示测试失败以及比较失败消息。

在关闭 IntelliJ 之前将 expectedValue 变量恢复为其原始值。

概括

此时,如果您在想 为什么不直接使用 System.out.println() 进行单元测试呢? 那你就想错了。将用于调试的 System.out.println() 插入到代码中是不可取的,因为它需要在每次程序运行时手动扫描输出,以确保代码按预期进行。想象一下在具有成百上千行代码的企业应用程序中执行此操作。另一方面,单元测试从客户端的角度检查代码在运行时的行为。这可以更好地了解软件发布时可能发生的情况。

每当您编写代码时,您也应该编写单元测试。编写单元测试将捕获编程错误并提高代码质量。许多专业开发人员提倡进行测试驱动开发 (TDD),即在编写应用程序代码之前先编写单元测试。

无论哪种方式,如果您在编写应用程序代码之前或之后编写单元测试,单元测试都会成为检测代码的宝贵资产。随着代码库的增长,您可以根据需要重构事物,并且更有信心您的更改不会产生意想不到的后果(即,您更改了一件事,却不小心破坏了另一件事)。

我关于使用 JUnit 进行单元测试的教程系列的第 2 部分 中,我将更深入地了解 JUnit 断言、JUnit 注释和 JUnit 测试套件。

使用 Spring 框架进行单元测试

测试是使用 Spring 框架的 企业应用程序开发 过程中不可或缺的一部分。 Spring Framework 的体系结构适用于模块化代码和更容易的单元测试。 Spring通过对底层测试框架进行抽象的TestContext Framework提供测试支持,例如JUnit和TestNG。您可以通过将 SpringJUnit4ClassRunner.class 设置为 @RunWith 注释的值来使用它。这告诉 Spring 使用 TestContext 的测试运行器而不是 JUnit 的内置测试运行器。我 在这里 写了一篇关于使用 JUnit 测试 Spring 应用程序的更深入的文章。