电子书 – Spring Cloud 指南 – NPI EA (分类=Spring Cloud)
announcement - icon

让我们开始使用 Spring Cloud 的微服务架构

>> 加入 Pro 并下载电子书

电子书 – Mockito – NPI EA (标签 = Mockito)
announcement - icon

模拟是单元测试的重要组成部分,Mockito 库使编写 清晰直观的单元测试 变得容易,用于您的 Java 代码。

通过我们的 Mockito 指南 开始模拟,并改进您的应用程序测试

下载电子书

电子书 – Java 并发 – NPI EA (分类=Java 并发)
announcement - icon

在应用程序中处理并发可能是一个棘手的过程,其中包含许多 潜在的陷阱。 扎实的掌握基本知识将有助于最大程度地减少这些问题。

通过我们的 Java 并发 指南开始了解多线程应用程序

>> 下载电子书

电子书 – 响应式 – NPI EA (分类=响应式)
announcement - icon

Spring 5 增加了对使用 Spring WebFlux 模块进行响应式编程的支持,此支持自那时起不断改进。 开始使用 Reactor 项目基础知识和 Spring Boot 中的响应式编程

>> 加入 Pro 并下载电子书

电子书 – Java Streams – NPI EA (分类=Java Streams)
announcement - icon

自从 Java 8 引入以来,Stream API 已成为 Java 开发的基础。 基本操作,例如迭代、过滤、映射元素序列,使用起来看似很简单。

但这些也可能被过度使用并陷入一些常见陷阱。

更好地了解 Stream 的工作方式 以及如何将其与其他语言功能结合使用,请查看我们关于 Java Streams 的指南

>> 加入 Pro 并下载电子书

电子书 – Jackson – NPI EA (分类=Jackson)
announcement - icon

用 Jackson 正确处理 JSON

下载电子书

电子书 – HTTP 客户端 – NPI EA (分类=Http 客户端)
announcement - icon

充分利用 Apache HTTP 客户端

下载电子书

电子书 – Maven – NPI EA (分类 = Maven)
announcement - icon

开始使用 Apache Maven

下载电子书

电子书 – 持久化 – NPI EA (分类=持久化)
announcement - icon

您在努力实现正确的持久化层 Spring 吗?

探索电子书

电子书 – RwS – NPI EA (分类=Spring MVC)
announcement - icon

使用 Spring 构建 REST API 吗?

下载电子书

课程 – LS – NPI EA (分类=Jackson)
announcement - icon

通过 Learn Spring 课程开始学习 Spring 和 Spring Boot

>> 学习 SPRING
课程 – RWSB – NPI EA (分类=REST)
announcement - icon

通过构建一个完整的 REST API,深入了解 Spring Boot 3 和 Spring 6,使用该框架

>> 全新的“REST With Spring Boot”

课程 – LSS – NPI EA (分类=Spring Security)
announcement - icon

是的,Spring Security 可能很复杂,从核心内的更高级功能到框架中深入的 OAuth 支持。

我将安全材料构建为 两个完整的课程 - 核心和 OAuth,以针对这些更复杂的场景进行实践。 我们探索何时以及如何使用每个功能,并 在后台项目中对其进行编码

您可以在这里探索该课程

>> 学习 Spring Security

课程 – LSD – NPI EA (标签=Spring Data JPA)
announcement - icon

Spring Data JPA 是处理 JPA 复杂性的绝佳方式,它具有 Spring Boot 的强大简洁性

通过引导式参考课程开始使用 Spring Data JPA

>> 查看课程

合作伙伴 – Moderne – NPI EA (类别=Spring Boot)
announcement - icon

使用 OpenRewrite 安全且自动地重构 Java 代码。

手动重构大型代码库既缓慢、有风险,又容易拖延。OpenRewrite 应运而生。这个用于大规模、自动化代码转换的开源框架可以帮助团队安全、一致地进行现代化改造。

每个月,OpenRewrite 的创建者和维护者 Moderne 都会举办现场、实践培训课程——一个面向初学者,一个面向经验丰富的用户。您将了解配方的运作方式、如何将其应用于项目,以及如何自信地进行代码现代化改造。

参加下一次课程,带来您的问题,并学习如何自动化通常会占用您 sprint 时间的工作。

合作伙伴 – LambdaTest – NPI EA (类别=测试)
announcement - icon

回归测试是发布流程中的重要步骤,以确保新代码不会破坏现有功能。随着代码库的不断发展,我们希望频繁运行这些测试,以便尽早发现任何问题。

确保这些测试以自动化的方式频繁运行的最佳方法当然是将其包含在 CI/CD 管道中。 这样,每次向仓库提交代码时,回归测试将自动执行。

在本教程中,我们将学习如何使用 Selenium 创建回归测试,然后使用 GitHub Actions 将它们包含在我们的管道中,在 LambdaTest 云网格上运行

>> 如何使用 GitHub Actions 运行 Selenium 回归测试

课程 – LJB – NPI EA (类别 = Core Java)
announcement - icon

通过编码方式构建 Java 的坚实、实用的基础

>> 学习 Java 基础

合作伙伴 – LambdaTest – NPI (类别 = 测试)
announcement - icon

回归测试是发布流程中的重要步骤,以确保新代码不会破坏现有功能。随着代码库的不断发展,我们希望频繁运行这些测试,以便尽早发现任何问题。

确保这些测试以自动化的方式频繁运行的最佳方法当然是将其包含在 CI/CD 管道中。 这样,每次向仓库提交代码时,回归测试将自动执行。

在本教程中,我们将学习如何使用 Selenium 创建回归测试,然后使用 GitHub Actions 将它们包含在我们的管道中,在 LambdaTest 云网格上运行

>> 如何使用 GitHub Actions 运行 Selenium 回归测试

课程 – LJU – NPI (标签 = JUnit)
announcement - icon

通过Learn JUnit课程掌握最流行的 Java 测试框架

>> 学习 JUnit

1. 概述

单元测试是软件设计和实现中的一个关键步骤。

它不仅可以提高代码的效率和有效性,还可以使代码更健壮,并减少未来开发和维护中的回归问题。

在本教程中,我们将讨论一些 Java 单元测试的最佳实践。

2. 什么是单元测试?

单元测试是一种测试源代码是否适合在生产环境中使用的方法论。

我们从通过创建各种测试用例来验证源代码单个单元的行为开始编写单元测试。

然后 完整的测试套件将执行以捕获回归,无论是在实现阶段还是在构建用于各种阶段部署的软件包时,例如预发布和生产环境。

让我们来看一个简单的场景。

首先,让我们创建 Circle 类并在其中实现 calculateArea 方法

public class Circle {

    public static double calculateArea(double radius) {
        return Math.PI * radius * radius;
    }
}

然后,我们将为 Circle 类创建单元测试,以确保 calculateArea 方法按预期工作。

让我们在 src/main/test 目录下创建 CalculatorTest

public class CircleTest {

    @Test
    public void testCalculateArea() {
        //...
    }
}

在这种情况下,我们使用 JUnit 的 @Test 注解 以及构建工具,例如 MavenGradle 来运行测试。

3. 最佳实践

3.1. 源代码

将测试类与主源代码分开是一个好主意。因此,它们与生产代码分开开发、执行和维护。

此外,它避免了在生产环境中运行测试代码的任何可能性。

我们可以按照构建工具(例如 Maven 和 Gradle)的步骤,这些工具会在 src/main/test 目录中查找测试实现。

3.2. 包命名约定

我们应该在 src/main/test 目录中为测试类创建类似的包结构,这样可以提高测试代码的可读性和可维护性。

简而言之,测试类的包应该与要测试的源代码类的包匹配。

例如,如果我们的 Circle 类存在于 com.baeldung.math 包中,则 CircleTest 类也应该存在于 src/main/test 目录结构下的 com.baeldung.math 包中。

3.3. 测试用例命名约定

测试名称应该具有洞察力,用户应该仅通过查看名称就能理解测试的行为和期望。

例如,我们的单元测试名称是 testCalculateArea,这对于任何有意义的测试场景和期望信息来说都过于模糊。

因此,我们应该以操作和期望来命名测试,例如 testCalculateAreaWithGeneralDoubleValueRadiusThatReturnsAreaInDoubletestCalculateAreaWithLargeDoubleValueRadiusThatReturnsAreaAsInfinity

但是,我们仍然可以改进名称以提高可读性。

通常有帮助的是以 given_when_then 的形式命名测试用例,以详细说明单元测试的目的:

public class CircleTest {

    //...

    @Test
    public void givenRadius_whenCalculateArea_thenReturnArea() {
        //...
    }

    @Test
    public void givenDoubleMaxValueAsRadius_whenCalculateArea_thenReturnAreaAsInfinity() {
        //...
    }
}

我们还应该GivenWhenThen 格式描述代码块。此外,它有助于将测试划分为三个部分:输入、操作和输出。

首先,与给定部分对应的代码块会创建测试对象,模拟数据并安排输入。

接下来,when 部分的代码块代表一个特定的动作或测试场景。

同样,then 部分指出了代码的输出,该输出会使用断言与预期结果进行验证。

3.4. 期望值与实际值

一个测试用例应该在期望值和实际值之间有一个断言。

为了佐证期望值与实际值的概念,我们可以查看 JUnit 的Assert 类中的 assertEquals 方法的定义

public static void assertEquals(Object expected, Object actual)

让我们在我们的一个测试用例中使用这个断言

@Test 
public void givenRadius_whenCalculateArea_thenReturnArea() {
    double actualArea = Circle.calculateArea(1d);
    double expectedArea = 3.141592653589793;
    Assert.assertEquals(expectedArea, actualArea); 
}

建议在变量名称前加上 “actual” (实际) 和 “expected” (期望) 关键字,以提高测试代码的可读性。

3.5. 偏爱简单的测试用例

在之前的测试用例中,我们可以看到期望值是硬编码的。这是为了避免为了获取期望值而在测试用例中重写或重用实际代码的实现。

不鼓励计算圆的面积来与 calculateArea 方法的返回值进行匹配

@Test 
public void givenRadius_whenCalculateArea_thenReturnArea() {
    double actualArea = Circle.calculateArea(2d);
    double expectedArea = 3.141592653589793 * 2 * 2;
    Assert.assertEquals(expectedArea, actualArea); 
}

在这种断言中,我们使用相似的逻辑来计算期望值和实际值,从而导致永远产生相似的结果。因此,我们的测试用例对代码的单元测试不会增加任何价值。

因此,我们应该创建一个简单的测试用例,将硬编码的期望值与实际值进行断言。

虽然有时需要在测试用例中编写逻辑,但我们不应该过度这样做。此外,正如常见的,我们绝不应该在测试用例中实现生产逻辑来通过断言。

3.6. 适当的断言

始终使用适当的断言来验证期望值与实际值的对比结果。 我们应该使用 JUnit 的Assert 类或类似框架(如 AssertJ)中提供的各种方法。

例如,我们已经使用了 Assert.assertEquals 方法进行值断言。类似地,我们可以使用 assertNotEquals 来检查期望值和实际值是否不相等。

其他方法,如 assertNotNullassertTrue 和 assertNotSame 在不同的断言中是有益的。

3.7. 具体的单元测试

不要将多个断言添加到同一个单元测试中,我们应该创建单独的测试用例。

当然,有时验证同一个测试中的多个场景是很有诱惑力的,但最好将它们分开。然后,在测试失败的情况下,将更容易确定哪个特定场景失败了,并且同样,更容易修复代码。

因此,始终编写一个单元测试来测试单个特定的场景。

一个单元测试不会变得过于复杂而难以理解。此外,以后调试和维护单元测试会更容易。

3.8. 测试生产场景

当我们编写测试时考虑到实际场景时,单元测试会更有价值。

原则上,这有助于使单元测试更具相关性。此外,它证明了理解代码在某些生产情况下的行为至关重要。

3.9. 模拟外部服务

尽管单元测试集中在特定的和较小的代码片段上,但代码可能依赖于外部服务来获取某些逻辑的可能性是存在的。

因此,我们应该模拟外部服务,而仅仅测试代码的逻辑和执行,针对不同的场景。

我们可以使用各种框架,如 MockitoEasyMock 和 JMockit 来模拟外部服务。

3.10. 避免代码冗余

创建更多和更多的 辅助函数来生成常用的对象,并模拟数据或外部服务,用于类似的单元测试。

与其它建议一样,这能增强测试代码的可读性和可维护性。

3.11. 注解

通常,测试框架会提供各种用途的注解,例如执行设置、在运行测试之前执行代码以及在运行测试之后进行清理。

我们可以使用各种注解,例如 JUnit 的 @Before, @BeforeClass 和 @After 以及来自其他测试框架(如 TestNG)的注解。

我们应该 利用注解来为测试准备系统,通过创建数据、安排对象并在每个测试之后删除所有内容,以保持测试用例之间的隔离。

3.12. 80% 测试覆盖率

更多 源代码的测试覆盖率始终是有益的。然而,这并非唯一的目标。我们应该做出明智的决定,并选择适合我们的实现、截止日期和团队的最佳权衡方案。

作为经验法则,我们应该 尝试用单元测试覆盖 80% 的代码。

此外,我们可以使用诸如 JaCoCoCobertura 之类的工具,以及 Maven 或 Gradle,来生成代码覆盖率报告。

3.13. TDD 方法

测试驱动开发 (TDD) 是一种在持续实现之前和期间创建测试用例的方法。这种方法与设计和实现源代码的过程相结合。

其优势包括 从一开始就可测试的生产代码、具有易于重构和更少回归的健壮实现。

3.14. 自动化

我们可以在创建新构建的同时 通过自动化执行整个测试套件来提高代码的可靠性

这主要有助于避免在各种发布环境中出现不幸的回归。它还确保在发布损坏的代码之前能够获得快速反馈。

因此,单元测试执行应成为 CI-CD 管道 的一部分,并在出现故障时提醒相关人员。

4. 结论

在本文中,我们探讨了 Java 单元测试的一些最佳实践。遵循最佳实践可以帮助软件开发的许多方面。

Baeldung Pro – NPI EA (类别 = Baeldung)
announcement - icon

Baeldung Pro 具有完全无广告以及最终具有深色模式,提供干净的学习体验

>> 探索干净的 Baeldung

一旦早期采用者的席位全部用完,价格将上涨并保持在每年 33 美元。

电子书 – HTTP 客户端 – NPI EA (类别=HTTP 客户端)
announcement - icon

Apache HTTP Client 是一个非常强大的库,适用于简单和高级用例,在测试 HTTP 端点时尤其适用。 查看我们的指南,涵盖基本请求和响应处理,以及安全性、Cookie、超时等。

>> 下载电子书

电子书 – Java 并发 – NPI EA (分类=Java 并发)
announcement - icon

在应用程序中处理并发可能是一个棘手的过程,其中包含许多 潜在的陷阱。 扎实的掌握基本知识将有助于最大程度地减少这些问题。

通过我们的 Java 并发 指南开始了解多线程应用程序

>> 下载电子书

电子书 – Java Streams – NPI EA (分类=Java Streams)
announcement - icon

自从 Java 8 引入以来,Stream API 已成为 Java 开发的基础。 基本操作,例如迭代、过滤、映射元素序列,使用起来看似很简单。

但这些也可能被过度使用并陷入一些常见陷阱。

更好地了解 Stream 的工作方式 以及如何将其与其他语言功能结合使用,请查看我们关于 Java Streams 的指南

>> 加入 Pro 并下载电子书

电子书 – 持久化 – NPI EA (分类=持久化)
announcement - icon

您在努力实现正确的持久化层 Spring 吗?

探索电子书

课程 – LS – NPI EA (类别=REST)

announcement - icon

从 Spring Boot 开始,通过 Learn Spring 课程了解核心 Spring。

>> 查看课程

合作伙伴 – Moderne – NPI EA (标签=重构)
announcement - icon

现代 Java 团队行动迅速——但代码库并不总是跟上。 框架会发生变化,依赖关系会漂移,技术债务会累积,直到它开始拖慢交付速度。 OpenRewrite 就是为此而构建的:一个开源重构引擎,可在保持开发人员意图不变的同时自动化重复的代码更改。

由 Moderne 的 OpenRewrite 创建者和维护者领导的每月培训系列,将介绍实际的迁移和现代化模式。 无论您是重构配方的新手,还是准备编写自己的配方,您都将学习以安全且可扩展的方式进行重构的实用方法。

如果您曾经希望重构感觉像编写代码一样自然——并且一样快速——这是一个很好的起点

电子书 Jackson – NPI EA – 3 (类别 = Jackson)
© .