提交 ba9b94db 编写于 作者: W wizardforcel

2021-10-06 00:42:56

上级 53d70d80
# 六、了解有关阵列的所有信息
# 六、了解有关数组的所有信息
在本章中,我们将了解 Java 代码中最重要的概念之一:数组。我们将看到不同数组的外观,以及如何初始化和显示它们。我们还将看一些练习,以帮助我们更好地了解数组的工作原理。
......
# 七、了解 Java11 中的日期类和构造函数
# 七、了解 Java11 中的日期类和构造
`Date`类和构造函数是 Java 的重要组成部分。在本章中,我们将通过一些示例详细讨论其中的每一个。
......
# 十、最终关键字、包和修饰符的重要性
# 十、`final`关键字、包和修饰符的重要性
这是我们这本书的最后一章。在这里,我们将讨论一些更重要的概念,这些概念将帮助我们编写和执行更好的代码
......
+ [Java 自动化测试初学者实用指南](README.md)
+ [零、前言](00.md)
+ [一、Java 中的第一个编程步骤](01.md)
+ [二、了解 Java 中的类、对象及其用法](02.md)
+ [三、在 Java 中处理字符串及其函数](03.md)
+ [四、Java 程序–循环和条件的构建块](04.md)
+ [五、您需要了解的关于接口和继承的所有信息](05.md)
+ [六、了解有关数组的所有信息](06.md)
+ [七、了解 Java11 中的日期类和构造器](07.md)
+ [八、`super`和`this`关键字和异常在 Java 中的重要性](08.md)
+ [九、理解集合框架](09.md)
+ [十、`final`关键字、包和修饰符的重要性](10.md)
......@@ -392,7 +392,7 @@ Java9 改进了争用锁定。您可能想知道什么是竞争锁定。让我
编译器改进的第二个显著变化是提前编译。如果您不熟悉这个术语,让我们看看 AOT 是什么。您可能知道,任何语言中的每个程序都需要运行时环境来执行。Java 也有自己的运行时,称为**Java 虚拟机****JVM**)。我们大多数人使用的典型运行时是字节码解释器,它也是 JIT 编译器。此运行时称为**HotspotJVM**
这个HotspotJVM 以通过 JIT 编译和自适应优化提高性能而闻名。到现在为止,一直都还不错。然而,这在实践中并不适用于每个应用程序。如果您有一个非常轻的程序,比如说,一个方法调用,该怎么办?在这种情况下,JIT 编译对您帮助不大。你需要一些能更快加载的东西。这就是 AOT 将帮助您的地方。使用 AOT 而不是 JIT,您可以编译为本机机器代码,而不是编译为字节码。然后,运行时使用此本机代码管理对`malloc`中新对象的调用以及对系统调用的文件访问。这可以提高性能。
这个 HotspotJVM 以通过 JIT 编译和自适应优化提高性能而闻名。到现在为止,一直都还不错。然而,这在实践中并不适用于每个应用程序。如果您有一个非常轻的程序,比如说,一个方法调用,该怎么办?在这种情况下,JIT 编译对您帮助不大。你需要一些能更快加载的东西。这就是 AOT 将帮助您的地方。使用 AOT 而不是 JIT,您可以编译为本机机器代码,而不是编译为字节码。然后,运行时使用此本机代码管理对`malloc`中新对象的调用以及对系统调用的文件访问。这可以提高性能。
# 安全管理器改进
......
......@@ -1194,7 +1194,7 @@ public static interface Flow.Processor<T,R>
这是响应流倡议为支持具有非阻塞背压的异步数据流而定义的最小接口集(现在是 JDK 9 的一部分)。如您所见,它允许订阅者和发布者相互交谈,并在需要时协调传入数据的速率,从而为我们在开始时讨论的背压问题提供多种解决方案。
有许多方法可以实现这些接口。目前,在 JDK 9 中,只有一个接口的实现示例,`SubmissionPublisher`类实现了`Flow.Publisher`。但是已经存在其他几个实现反应流 API 的库:RxJava、Reactor、Akka Streams 和 Vert.x 是最有名的库。我们将在示例中使用 RXJava2.1.3。您可以在[这里](http://reactivex.io)找到 RxJava 2.x API名称为 ReactiveX,表示被动扩展。
有许多方法可以实现这些接口。目前,在 JDK 9 中,只有一个接口的实现示例,`SubmissionPublisher`类实现了`Flow.Publisher`。但是已经存在其他几个实现反应流 API 的库:RxJava、Reactor、Akka Streams 和 Vert.x 是最有名的库。我们将在示例中使用 RXJava2.1.3。您可以在[这里](http://reactivex.io)找到 RxJava 2.x API 名称为 ReactiveX,表示被动扩展。
在这样做的同时,我们还希望解决`java.util.stream`包的流和反应流(例如,在 RxJava 中实现的)之间的差异。可以使用任何流编写非常类似的代码。让我们看一个例子。这是一个程序,它迭代五个整数,只选择偶数(2 和 4),变换每个整数(取每个所选数的平方根),然后计算两个平方根的平均值。它基于传统的`for`循环。
......
+ [零、序言](0.md)
+ [一、学习 Java 9 底层性能改进](1.md)
+ [二、提高生产率和更快应用的工具](2.md)
+ [三、多线程和反应式编程](3.md)
+ [四、微服务](4.md)
+ [五、利用新 API 改进代码](5.md)
+ [六、评估答案](6.md)
+ [Java9 高性能应用](README.md)
\ No newline at end of file
......@@ -643,7 +643,7 @@ ModuleStatement:
前面命令中的关键部分是`--main-class`选项。这使我们能够执行 JAR,而不必在执行期间提供主类信息。
4. 现在,我们在`mlib`目录中有两个 JAR:`math.util@1.0.jar``calculator@1.0.jar`。这些JAR被称为模块化JAR。如果要运行该示例,可以使用以下命令:
4. 现在,我们在`mlib`目录中有两个 JAR:`math.util@1.0.jar``calculator@1.0.jar`。这些 JAR 被称为模块化 JAR。如果要运行该示例,可以使用以下命令:
```java
java -p mlib -m calculator
......@@ -694,7 +694,7 @@ math.util@1.0
# 在项目前 JigsawJDK 应用程序中使用模块 JAR
如果我们的模块化 JAR 能够与项目前的 JigsawJDK 应用程序一起运行,那将是一件令人惊讶的事情。这样,我们就不用为 JDK 9 之前的应用程序编写另一个版本的 API 了。好消息是,我们可以像使用普通JAR一样使用模块化JAR,也就是说,JAR的根部没有`module-info.class`。我们将在这个食谱中看到如何做到这一点。
如果我们的模块化 JAR 能够与项目前的 JigsawJDK 应用程序一起运行,那将是一件令人惊讶的事情。这样,我们就不用为 JDK 9 之前的应用程序编写另一个版本的 API 了。好消息是,我们可以像使用普通 JAR 一样使用模块化 JAR,也就是说,JAR 的根部没有`module-info.class`。我们将在这个食谱中看到如何做到这一点。
# 准备
......@@ -706,7 +706,7 @@ mkdir mlib
jar --create --file mlib/math.util.jar -C classes/math.util .
```
我们还提供了一个位于`Chapter03/4_modular_jar_with_pre_java9``jar-math.bat`脚本,可用于在 Windows 上创建模块化 JAR。我们有我们的模块化JAR。让我们使用`jar`命令的`-d`选项进行验证:
我们还提供了一个位于`Chapter03/4_modular_jar_with_pre_java9``jar-math.bat`脚本,可用于在 Windows 上创建模块化 JAR。我们有我们的模块化 JAR。让我们使用`jar`命令的`-d`选项进行验证:
```java
jar -d --file mlib/math.util@1.0.jar
......@@ -723,7 +723,7 @@ math.util@1.0
此时,您应该具备以下条件:
* 一个名为`math.util@1.0.jar`的模块化JAR
* 一个名为`math.util@1.0.jar`的模块化 JAR
*`NonModularCalculator`包组成的非模块化应用程序
现在,我们需要编译我们的`NonModularCalculator`类:
......@@ -814,7 +814,7 @@ javac -cp calculator/lib/*:math_util/out/math.util.jar:banking_util/out/banking.
jar --create --file=calculator/out/calculator.jar -C calculator/out/classes/ .
```
请注意,我们的 Jackson JAR位于`calculator/lib`中,因此您无需担心下载它们。让我们使用以下命令运行计算器:
请注意,我们的 Jackson JAR 位于`calculator/lib`中,因此您无需担心下载它们。让我们使用以下命令运行计算器:
```java
java -cp calculator/out/classes:calculator/lib/*:math_util/out/math.util.jar:banking_util/out/banking.util.jar com.packt.calculator.Calculator
......@@ -886,9 +886,9 @@ math.util.jar -> java.base
jar --create --file=mlib/banking.util.jar -C mods/banking.util .
```
如果您想知道什么是模块化JAR,请随意阅读本章中的“创建模块化 JAR”配方。
如果您想知道什么是模块化 JAR,请随意阅读本章中的“创建模块化 JAR”配方。
现在我们已经模块化了`banking.util.jar`,让我们使用这个模块化的`jar`来代替前面“准备”部分中使用的非模块化JAR。您应该从`6_bottom_up_migration_before`文件夹执行以下操作,因为我们尚未完全模块化应用程序:
现在我们已经模块化了`banking.util.jar`,让我们使用这个模块化的`jar`来代替前面“准备”部分中使用的非模块化 JAR。您应该从`6_bottom_up_migration_before`文件夹执行以下操作,因为我们尚未完全模块化应用程序:
```java
java --add-modules ALL-MODULE-PATH --module-path ../6_bottom_up_migration_after/mods/banking.util -cp calculator/out/classes:calculator/lib/*:math_util/out/math.util.jar com.packt.calculator.Calculator
......@@ -944,7 +944,7 @@ java --add-modules ALL-MODULE-PATH --module-path ../6_bottom_up_migration_after/
我们无法对`calculator.jar`进行模块化,因为它依赖于另一个非模块化代码`jackson-databind`,我们无法对`jackson-databind`进行模块化,因为它不是由我们维护的。这意味着我们无法实现应用程序的 100% 模块化。在本配方的开头,我们向您介绍了未命名的模块。我们在类路径中的所有非模块代码都分组在未命名的模块中,这意味着所有与 Jackson 相关的代码仍然可以保留在未命名的模块中,我们可以尝试模块化`calculator.jar`。但是我们不能这样做,因为`calculator.jar`不能声明对`jackson-databind-2.8.4.jar`的依赖关系(因为它是一个未命名的模块,命名的模块不能声明对未命名模块的依赖关系)。
解决这个问题的一种方法是将与 Jackson 相关的代码作为自动模块。我们可以通过移动与 Jackson 相关的JAR来实现这一点:
解决这个问题的一种方法是将与 Jackson 相关的代码作为自动模块。我们可以通过移动与 Jackson 相关的 JAR 来实现这一点:
* `jackson-databind-2.8.4.jar`
* `jackson-annotations-2.8.4.jar`
......@@ -1731,7 +1731,7 @@ com/packt/CollectionsDemo has been compiled by a more recent version of the Java
jar -tvf mr.jar
```
JAR的内容如下:
JAR 的内容如下:
![](img/ea10f27a-5853-477a-a589-4beba6202ae3.png)
......
此差异已折叠。
......@@ -367,7 +367,7 @@ public class UsernamePasswordAuthenticator
# 准备
`Chapter10/5_apache_http_demo/mods`中已经存在所有需要的JAR:
`Chapter10/5_apache_http_demo/mods`中已经存在所有需要的 JAR:
![](img/b3865825-465b-4302-9f43-8af7bb556344.png)
......
......@@ -2,7 +2,7 @@
本章介绍如何测试应用程序如何捕获和自动测试用例,如何在 API 与其他组件集成之前对其进行单元测试,以及如何集成所有单元。我们将向您介绍**行为驱动开发****BDD**),并展示它如何成为您应用程序开发的起点。我们还将演示 JUnit 框架如何用于单元测试。有时,在单元测试期间,我们必须使用一些虚拟数据来插桩依赖项,这可以通过模拟依赖项来完成。我们将向您展示如何使用模拟库来实现这一点。我们还将向您展示如何编写夹具来填充测试数据,以及如何通过集成不同的 API 并将它们测试在一起来测试应用程序的行为。我们将介绍以下配方:
* Cucumber行为测试
* Cucumber 行为测试
* 使用 JUnit 对 API 进行单元测试
* 通过模拟依赖项进行单元测试
* 使用夹具填充测试数据
......@@ -20,7 +20,7 @@
从方法论上讲,本章的内容也适用于其他语言和专业,但这些示例主要是为 Java 开发人员编写的。
# Cucumber行为测试
# Cucumber 行为测试
以下是程序员经常抱怨的三个问题:
......@@ -30,7 +30,7 @@
有相当多的建议和程序有助于缓解这些问题,但没有一个能够完全消除这些问题。在我们看来,最成功的是与 BDD 结合使用的敏捷过程方法,使用 Cucumber 或其他类似的框架。短迭代允许在业务(客户)和程序员之间进行快速调整和协调,而带有 Cucumber 的 BDD 用一种称为 Gherkin 的正式语言捕获需求,但不需要维护大量文档。
Cucumber编写的需求必须分解为**特征**。每个功能都存储在一个扩展名为`.feature`的文件中,由一个或多个**场景**组成,这些场景描述了功能的不同方面。每个场景由描述用户操作或输入数据以及应用程序如何响应的步骤组成。
Cucumber 编写的需求必须分解为**特征**。每个功能都存储在一个扩展名为`.feature`的文件中,由一个或多个**场景**组成,这些场景描述了功能的不同方面。每个场景由描述用户操作或输入数据以及应用程序如何响应的步骤组成。
程序员实现必要的应用程序功能,然后使用它在一个或多个`.java`文件中实现场景。每个步骤都在一个方法中实现。
......@@ -40,7 +40,7 @@
# 怎么做。。。
1. 安装Cucumber。Cucumber 安装只不过是将框架作为 Maven 依赖项添加到项目中。由于我们要添加几个 Cucumber JAR 文件,并且所有文件都必须具有相同的版本,因此首先在`pom.xml`中添加`cucumber.version`属性是有意义的:
1. 安装 Cucumber。Cucumber 安装只不过是将框架作为 Maven 依赖项添加到项目中。由于我们要添加几个 Cucumber JAR 文件,并且所有文件都必须具有相同的版本,因此首先在`pom.xml`中添加`cucumber.version`属性是有意义的:
```java
<properties>
......@@ -110,7 +110,7 @@
如您所见,在本例中,您需要添加`cucumber-testng`JAR 文件,而不是`cucumber-junit`JAR 文件。TestNG 提供了丰富多样的断言方法,包括深度集合和其他对象比较。
2. 运行Cucumber。`cucumber-junit`JAR 文件还提供了一个`@RunWith`注释,将一个类指定为测试运行程序:
2. 运行 Cucumber。`cucumber-junit`JAR 文件还提供了一个`@RunWith`注释,将一个类指定为测试运行程序:
```java
package com.packt.cookbook.ch16_testing;
......
......@@ -52,7 +52,7 @@ JavaFX 不再与 JDK11 绑定(既不是 oraclejdk,也不是 OpenJDK 构建
* `javafx.swing`
* `javafx.web`
如果您使用的是 OracleJDK10 和 9,它附带了前面提到的 JavaFX 模块作为设置的一部分;也就是说,您可以在`JAVA_HOME/jmods`目录中找到它们。如果您使用的是 OpenJDK10 及 JDK11,则需要[下载 JavaFXSDK](https://gluonhq.com/products/javafx/),并在您的`modulepath`上提供`JAVAFX_SDK_PATH/libs`位置的JAR,如下所示:
如果您使用的是 OracleJDK10 和 9,它附带了前面提到的 JavaFX 模块作为设置的一部分;也就是说,您可以在`JAVA_HOME/jmods`目录中找到它们。如果您使用的是 OpenJDK10 及 JDK11,则需要[下载 JavaFXSDK](https://gluonhq.com/products/javafx/),并在您的`modulepath`上提供`JAVAFX_SDK_PATH/libs`位置的 JAR,如下所示:
```java
javac -p "PATH_TO_JAVAFX_SDK_LIB" <other parts of the command line>
......@@ -854,7 +854,7 @@ java -p "PATH_TO_JAVAFX_SDK_LIB:COMPILED_CODE" <other parts of the command line>
* `3`:中等教育
* `4`:高等教育
我们已经创建了一个用于处理学生文件的模块。模块名称为`student.processor`,其代码可在`Chapter16/101_student_data_processor`找到。因此,如果您想更改那里的任何代码,您可以通过运行`build-jar.bat``build-jar.sh`文件来重建 JAR。这将在`mlib`目录中创建一个模块化 JAR`student.processor.jar`。然后,你必须用这个配方的`mlib`目录中的一个,即`Chapter16/4_bar_charts/mlib`来替换这个模块化JAR。
我们已经创建了一个用于处理学生文件的模块。模块名称为`student.processor`,其代码可在`Chapter16/101_student_data_processor`找到。因此,如果您想更改那里的任何代码,您可以通过运行`build-jar.bat``build-jar.sh`文件来重建 JAR。这将在`mlib`目录中创建一个模块化 JAR`student.processor.jar`。然后,你必须用这个配方的`mlib`目录中的一个,即`Chapter16/4_bar_charts/mlib`来替换这个模块化 JAR。
我们建议您从`Chapter16/101_student_data_processor`中提供的源代码构建`student.processor`模块化 JAR。我们提供了`build-jar.bat``build-jar.sh`脚本来帮助您构建 JAR。您只需运行与平台相关的脚本,然后将`101_student_data_processor/mlib`中的 JAR 构建复制到`4_bar_charts/mlib`
......
+ [零、序言](00.md)
+ [一、安装和对 Java11 的窥探](01.md)
+ [二、面向对象编程的快速通道-类和接口](02.md)
+ [三、模块化编程](03.md)
+ [四、发挥作用](04.md)
+ [五、流和管道](05.md)
+ [六、数据库编程](06.md)
+ [七、并发和多线程编程](07.md)
+ [八、更好地管理操作系统进程](08.md)
+ [九、使用 springboot 的 restfulWeb 服务](09.md)
+ [十、网络](10.md)
+ [十一、内存管理和调试](11.md)
+ [十二、使用 JShell 的读取-计算打印循环(REPL)](12.md)
+ [十三、使用新的日期和时间 API](13.md)
+ [十四、测试](14.md)
+ [十五、Java10 和 Java11 编码的新方法](15.md)
+ [十六、使用 JavaFX 进行 GUI 编程](16.md)
+ [Java11 秘籍](README.md)
\ No newline at end of file
......@@ -152,7 +152,7 @@ JUnit Lambda 项目成为 JUnit 5,指导开发过程的设计原则如下:
JUnit5 贡献者不仅仅是开发人员。贡献者也是测试人员、维护人员和沟通者。在撰写本文时,GitHub 上排名前 5 的贡献者是:
* Sam Brannen([@Sam_Brannen](https://twitter.com/sam_brannen)):核心 Spring 框架和 JUnit 5 提交人。Swiftmind 的企业 Java 顾问。Spring&JUnit教练。会议发言人。
* Sam Brannen([@Sam_Brannen](https://twitter.com/sam_brannen)):核心 Spring 框架和 JUnit 5 提交人。Swiftmind 的企业 Java 顾问。Spring&JUnit 教练。会议发言人。
* Marc Philipp([@MarchPhilipp](https://twitter.com/marcphilipp)):LogMeIn 的高级软件工程师,积极参与 JUnit 或 Usus 等开源项目。会议发言人。
* johanneslink([@johanneslink](https://twitter.com/johanneslink)):程序员和软件治疗师。JUnit5 的支持者。
* Matthias Merdes:德国海德堡美孚股份有限公司的首席开发商。
......@@ -359,7 +359,7 @@ launcher.execute(request);
本书的所有源代码都可以在 [GitHub 存储库](https://github.com/bonigarcia/mastering-junit5)上公开获取。
最后但并非最不重要的一点是,我们需要创建一个 Jupiter 测试用例。到目前为止,我们还没有学会如何实现 Jupiter 测试(这部分在第 3 章JUnit 5 标准测试中介绍)。然而,我们在这里执行的测试是演示 JUnit5 框架执行的最简单的测试。Jupiter 测试在其最小表达式中只是一个 Java 类,其中一个(或多个)方法用`@Test`(包`org.junit.jupiter.api`)注释。以下代码段提供了一个示例:
最后但并非最不重要的一点是,我们需要创建一个 Jupiter 测试用例。到目前为止,我们还没有学会如何实现 Jupiter 测试(这部分在第 3 章 JUnit 5 标准测试中介绍)。然而,我们在这里执行的测试是演示 JUnit5 框架执行的最简单的测试。Jupiter 测试在其最小表达式中只是一个 Java 类,其中一个(或多个)方法用`@Test`(包`org.junit.jupiter.api`)注释。以下代码段提供了一个示例:
```java
package io.github.bonigarcia;
......
......@@ -409,7 +409,7 @@ class TimeoutExceededTest {
![](img/00048.gif)
assertTimeout第一例控制台输出
assertTimeout 第一例控制台输出
让我们看看更多使用`assertTimeout`的测试。在第一个测试中,`assertTimeout`在给定的超时时间内将一段代码作为 Lambda 表达式进行求值,得到结果。在第二个测试中,`assertTimeout`在给定的超时时间内评估一个方法,获得其结果:
......
......@@ -820,7 +820,7 @@ public class MySpringApplication {
}
```
# Spring模块
# Spring 模块
Spring 框架是模块化的,允许开发人员只使用框架提供的所需模块。此模块的完整列表可在[这里](https://spring.io/projects)找到。下表总结了一些最重要的问题:
......@@ -835,14 +835,14 @@ Spring 框架是模块化的,允许开发人员只使用框架提供的所需
| Spring 集成 | ![](img/00113.jpeg) | 为基于 Spring 的应用程序提供轻量级、基于 POJO 的消息传递,以便与外部系统集成。 |
| SpringBatch | ![](img/00114.jpeg) | 提供一个轻量级框架,旨在为企业系统的操作开发健壮的批处理应用程序。 |
# Spring试验简介
# Spring 试验简介
Spring 是一个名为`spring-test`的模块,支持 Spring 组件的单元测试和集成测试。在其他特性中,该模块提供了创建用于测试目的的 Spring 应用程序上下文的能力,或者创建用于单独测试代码的模拟对象的能力。有不同的注释支持此测试功能。最重要的一项清单如下:
* `@ContextConfiguration`:此注释用于确定如何为集成测试加载和配置`ApplicationContext`。例如,它允许从注释类(使用元素类)或 XML 文件中声明的 Bean 定义(使用元素位置)加载应用程序上下文。
* `@ActiveProfiles`:此注释用于指示容器在应用程序上下文加载期间应激活哪些定义配置文件(例如,开发和测试配置文件)。
* `@TestPropertySource`:此注释用于配置属性文件的位置和要添加的内联属性。
* `@WebAppConfiguration`:此注释用于指示Spring上下文`ApplicationContext`加载的是`WebApplicationContext.`
* `@WebAppConfiguration`:此注释用于指示 Spring 上下文`ApplicationContext`加载的是`WebApplicationContext.`
此外,`spring-test`模块还提供了多种功能来执行测试中通常需要的不同操作,即:
......@@ -851,11 +851,11 @@ Spring 是一个名为`spring-test`的模块,支持 Spring 组件的单元测
* `org.springframework.test.jdbc`包包含类`JdbcTestUtils`,它是 JDBC 实用程序函数的集合,旨在简化标准数据库访问。
* `org.springframework.test.util`包包含类`ReflectionTestUtils`,它是一组实用方法的集合,用于在测试应用程序代码时设置非公共字段或调用私有/受保护的设置器方法。
# 测试 SpringBoot应用程序
# 测试 SpringBoot 应用程序
如前所述,Spring Boot 是 Spring 产品组合的一个项目,旨在简化 Spring 应用程序的开发。使用 Spring Boot 的主要好处总结如下:
* SpringBoot应用程序只是一个 Spring`ApplicationContext`,其中使用了配置上的主要约定。多亏了这一点,我们可以更快地开始 Spring 开发。
* SpringBoot 应用程序只是一个 Spring`ApplicationContext`,其中使用了配置上的主要约定。多亏了这一点,我们可以更快地开始 Spring 开发。
* 注释`@SpringBootApplication`用于标识 Spring Boot 项目中的主类。
* 提供了一系列开箱即用的非功能特性:嵌入式 servlet 容器(Tomcat、Jetty 和 Undertow)、安全性、度量、运行状况检查或外部化配置。
* 创建仅使用命令`java -jar`运行的独立运行应用程序(即使对于 Web 应用程序也是如此)。
......@@ -865,25 +865,25 @@ Spring 是一个名为`spring-test`的模块,支持 Spring 组件的单元测
| **名称** | **说明** |
| --- | --- |
| `spring-boot-starter` | 核心启动器,包括自动配置支持和日志记录 |
| `spring-boot-starter-batch` | SpringBatch起动器 |
| `spring-boot-starter-batch` | SpringBatch 起动器 |
| `spring-boot-starter-cloud-connectors` | 使用`SpringCloudConnectors`的启动器,它简化了与云平台(如 CloudFoundry 和 Heroku)中的服务的连接 |
| `spring-boot-starter-data-jpa` | 将 Spring 数据 JPA 与 Hibernate 结合使用的启动程序 |
| `spring-boot-starter-integration` | 使用 Spring 集成的启动器 |
| `spring-boot-starter-jdbc` | 将 JDBC 与 Tomcat JDBC 连接池一起使用的启动器 |
| `spring-boot-starter-test` | 用于使用库(包括 JUnit、Hamcrest 和 Mockito)测试 SpringBoot应用程序的启动器 |
| `spring-boot-starter-test` | 用于使用库(包括 JUnit、Hamcrest 和 Mockito)测试 SpringBoot 应用程序的启动器 |
| `spring-boot-starter-thymeleaf` | 用于使用 IELAF 视图构建 MVC Web 应用程序的启动器 |
| `spring-boot-starter-web` | 使用 SpringMVC 构建 Web(包括 REST)应用程序的启动器。使用 Tomcat 作为默认的嵌入式容器 |
| `spring-boot-starter-websocket` | 使用 Spring 框架的 WebSocket 支持构建 WebSocket 应用程序的启动器 |
有关 Spring Boot 的完整信息,请访问[官方参考资料](https://projects.spring.io/spring-boot/)
SpringBoot 提供了不同的功能来简化测试。例如,它提供了`@SpringBootTest`注释,用于测试类的类级别。此注释将为这些测试创建`ApplicationContext`(与`@ContextConfiguration`类似,但用于基于 SpringBoot的应用程序)。正如我们在前面的章节中所看到的,`spring-test`模块中,我们使用注释`@ContextConfiguration(classes=… )`来指定要加载的 Bean 定义(Spring`@Configuration`。在测试 SpringBoot应用程序时,这通常不是必需的。SpringBoot 的测试注释将自动搜索主配置(如果没有明确定义)。搜索算法从包含测试的包开始,直到找到一个`@SpringBootApplication`注释类。
SpringBoot 提供了不同的功能来简化测试。例如,它提供了`@SpringBootTest`注释,用于测试类的类级别。此注释将为这些测试创建`ApplicationContext`(与`@ContextConfiguration`类似,但用于基于 SpringBoot 的应用程序)。正如我们在前面的章节中所看到的,`spring-test`模块中,我们使用注释`@ContextConfiguration(classes=… )`来指定要加载的 Bean 定义(Spring`@Configuration`。在测试 SpringBoot 应用程序时,这通常不是必需的。SpringBoot 的测试注释将自动搜索主配置(如果没有明确定义)。搜索算法从包含测试的包开始,直到找到一个`@SpringBootApplication`注释类。
SpringBoot 还促进了对 Spring 组件使用模拟。为此,提供了注释`@MockBean`。此注释允许在`ApplicationContext`中为 Bean 定义 Mockito 模拟。它可以是新的 Bean,但也可以替换单个现有的 Bean 定义。模拟 Bean 在每个测试方法之后自动重置。这种方法通常被称为容器内测试,与容器外测试相对应,其中使用模拟库(例如,Mockito)对Spring组件进行单元测试,以隔离,而不需要Spring`ApplicationContext`。例如,Spring 应用程序的两种单元测试的示例将在下一节中显示。
SpringBoot 还促进了对 Spring 组件使用模拟。为此,提供了注释`@MockBean`。此注释允许在`ApplicationContext`中为 Bean 定义 Mockito 模拟。它可以是新的 Bean,但也可以替换单个现有的 Bean 定义。模拟 Bean 在每个测试方法之后自动重置。这种方法通常被称为容器内测试,与容器外测试相对应,其中使用模拟库(例如,Mockito)对 Spring 组件进行单元测试,以隔离,而不需要 Spring`ApplicationContext`。例如,Spring 应用程序的两种单元测试的示例将在下一节中显示。
# 用于 Spring 的 JUnit5 扩展
为了将`spring-test`功能集成到 JUnit5 的 Jupiter 编程模型中,开发了`SpringExtension`。从Spring 5 开始,此延长件是`spring-test`模块的一部分。让我们一起来看看 JUnit5 和 Spring5 的几个示例。
为了将`spring-test`功能集成到 JUnit5 的 Jupiter 编程模型中,开发了`SpringExtension`。从 Spring 5 开始,此延长件是`spring-test`模块的一部分。让我们一起来看看 JUnit5 和 Spring5 的几个示例。
假设我们要对前一节中描述的 Spring 应用程序进行容器内集成测试,该测试由三个类组成:`MySpringApplication``MessageComponent``MessageService`。正如我们所了解的,为了针对该应用程序实施 Jupiter 测试,我们需要执行以下步骤:
......@@ -920,7 +920,7 @@ class SimpleSpringTest {
}
```
这是一个非常简单的示例,其中评估了名为`MessageComponent`Spring组件。当本测试开始时,我们的`ApplicationContext`启动,所有Spring组件都在里面。之后,在本例中,将 Bean`MessageComponent`注入测试中,只需调用方法`getMessage()`并验证其响应即可对其进行评估。
这是一个非常简单的示例,其中评估了名为`MessageComponent` Spring 组件。当本测试开始时,我们的`ApplicationContext`启动,所有 Spring 组件都在里面。之后,在本例中,将 Bean`MessageComponent`注入测试中,只需调用方法`getMessage()`并验证其响应即可对其进行评估。
值得回顾一下此测试需要哪些依赖项。使用 Maven 时,这些依赖项如下所示:
......@@ -1164,7 +1164,7 @@ class SimpleSpringBootTest {
在控制台中执行测试时,我们可以看到应用程序实际上是在测试之前启动的(请注意开头的 spring ASCII 横幅)。
之后,我们的测试使用`ApplicationContext`对一个Spring组件进行验证,结果测试成功:
之后,我们的测试使用`ApplicationContext`对一个 Spring 组件进行验证,结果测试成功:
![](img/00115.gif)
......@@ -1220,7 +1220,7 @@ public class PageService {
示例项目`junit5 spring boot web`的内容
让我们继续讨论有趣的部分:测试。我们正在这个项目中实施三个 Jupiter 测试。第一个用于验证对页面`/index.html`的直接调用。如前所述,该测试需要使用Spring延长件(`@ExtendWith(SpringExtension.class)`并声明为Spring启动测试(`@SpringBootTest`。为了实现对 Web 应用程序的请求,我们使用了一个`MockMvc`实例,通过几种方式(HTTP 响应代码、内容类型和响应内容体)验证响应。此实例使用 Spring Boot 注释`@AutoConfigureMockMvc`自动配置。
让我们继续讨论有趣的部分:测试。我们正在这个项目中实施三个 Jupiter 测试。第一个用于验证对页面`/index.html`的直接调用。如前所述,该测试需要使用 Spring 延长件(`@ExtendWith(SpringExtension.class)`并声明为 Spring 启动测试(`@SpringBootTest`。为了实现对 Web 应用程序的请求,我们使用了一个`MockMvc`实例,通过几种方式(HTTP 响应代码、内容类型和响应内容体)验证响应。此实例使用 Spring Boot 注释`@AutoConfigureMockMvc`自动配置。
在 Spring Boot 之外,可以使用名为`MockMvcBuilders`的构建器类来创建对象`MockMvc`,而不是使用`@AutoConfigureMockMvc`。在本例中,应用程序上下文用作该生成器的参数。
......@@ -1265,7 +1265,7 @@ class IndexTest {
容器内首次测试的控制台输出
第二个测试类似,但作为一个差异因素,它使用测试能力`@MockBean`通过模拟覆盖Spring组件(在本例中为`PageService`)。在测试主体中,首先我们将模拟的方法`getPage`插桩,以将组件的默认响应更改为`redirect:/page.html`。因此,当使用对象`MockMvc`在测试中请求资源`/`时,我们将获得一个 HTTP 302 响应(重定向)到资源`/page.html`(实际上是一个现有页面,如项目截图所示):
第二个测试类似,但作为一个差异因素,它使用测试能力`@MockBean`通过模拟覆盖 Spring 组件(在本例中为`PageService`)。在测试主体中,首先我们将模拟的方法`getPage`插桩,以将组件的默认响应更改为`redirect:/page.html`。因此,当使用对象`MockMvc`在测试中请求资源`/`时,我们将获得一个 HTTP 302 响应(重定向)到资源`/page.html`(实际上是一个现有页面,如项目截图所示):
```java
package io.github.bonigarcia;
......@@ -1358,7 +1358,7 @@ class OutOfContainerTest {
# 简言之,Selenium
Selenium由不同的项目组成。首先,我们找到了Selenium IDE。它是一个 Firefox 插件,为 Web 应用程序实现**记录和回放****R&P**)模式。因此,它允许记录与 Firefox 的手动交互以及以自动方式进行的回放。
Selenium 由不同的项目组成。首先,我们找到了 Selenium IDE。它是一个 Firefox 插件,为 Web 应用程序实现**记录和回放****R&P**)模式。因此,它允许记录与 Firefox 的手动交互以及以自动方式进行的回放。
第二个项目名为**SeleniumRemoteControl****RC**)。该组件能够使用不同的编程语言(如 Java、C#、Python、Ruby、PHP、Perl 或 JavaScript)自动驱动不同类型的浏览器。该组件在 SUT 中注入了一个 JavaScript 库(称为 Selenium Core)。该库由一个名为 Selenium RC Server 的中间组件控制,该组件接收来自测试代码的请求(参见下图)。由于同源策略,Selenium RC 存在重要的安全问题。
......@@ -1602,11 +1602,11 @@ public class AppiumTest {
# Cucumber
Cucumber 执行用名为 Gherkin 的语言编写的指定测试。它是一种具有给定结构的纯文本自然语言(例如,英语或 Cucumber 支持的其他 60 多种语言之一)。Cucumber被设计成供非程序员使用,通常是客户、业务分析、经理等等。
Cucumber 执行用名为 Gherkin 的语言编写的指定测试。它是一种具有给定结构的纯文本自然语言(例如,英语或 Cucumber 支持的其他 60 多种语言之一)。Cucumber 被设计成供非程序员使用,通常是客户、业务分析、经理等等。
Cucumber文件的扩展名为`*.feature*`
Cucumber 文件的扩展名为`*.feature*`
Cucumber文件中,非空行可以以关键字开头,然后是自然语言中的文本。主要关键词如下:
Cucumber 文件中,非空行可以以关键字开头,然后是自然语言中的文本。主要关键词如下:
* **特性**:待测试软件特性的高层描述。它可以看作是一个用例描述。
* **场景**:说明业务规则的具体示例。场景遵循相同的模式:
......@@ -1614,7 +1614,7 @@ Cucumber文件的扩展名为`*.feature*`。
* 描述一个事件。
* 描述预期结果。
这些动作在Cucumber术语中被称为步骤,主要是**给出****当**,或**然后**
这些动作在 Cucumber 术语中被称为步骤,主要是**给出****当**,或**然后**
有两个额外的步骤:**和**(用于逻辑和不同的步骤)和**但**(用于**和**的否定形式)。
......@@ -1627,7 +1627,7 @@ Cucumber文件的扩展名为`*.feature*`。
当一行不以关键字开头时,Cucumber 不会解释该行。它用于自定义描述。
一旦我们定义了要测试的功能,我们就需要所谓的*步骤定义*,它允许将纯文本Cucumber翻译成实际执行 SUT 的动作。在 Java 中,可以很容易地通过注释对步骤实现的方法进行注释:`@Given``@Then``@When``@And``@But`。每个步骤的字符串值可以包含正则表达式,这些正则表达式在方法中映射为字段。请参见下一节中的示例。
一旦我们定义了要测试的功能,我们就需要所谓的*步骤定义*,它允许将纯文本 Cucumber 翻译成实际执行 SUT 的动作。在 Java 中,可以很容易地通过注释对步骤实现的方法进行注释:`@Given``@Then``@When``@And``@But`。每个步骤的字符串值可以包含正则表达式,这些正则表达式在方法中映射为字段。请参见下一节中的示例。
# Cucumber JUnit 5 的扩展
......@@ -1639,7 +1639,7 @@ Cucumber artifacts for Java 的最新版本包含一个 JUnit 5 Cucumber 扩展
JUnit5 与 Cucumber 项目结构和内容
首先,我们需要创建Cucumber文件,该文件旨在测试一个简单的计算器系统。这个计算器将是 SUT 或我们的测试。我们的专题文件内容如下:
首先,我们需要创建 Cucumber 文件,该文件旨在测试一个简单的计算器系统。这个计算器将是 SUT 或我们的测试。我们的专题文件内容如下:
```java
Feature: Basic Arithmetic
......@@ -1660,7 +1660,7 @@ Feature: Basic Arithmetic
| 3 | 7 | 10 |
```
然后,我们需要实现步骤定义。如前所述,我们使用注释和正则表达式将Cucumber文件中包含的文本映射到 SUT 的实际练习,具体取决于以下步骤:
然后,我们需要实现步骤定义。如前所述,我们使用注释和正则表达式将 Cucumber 文件中包含的文本映射到 SUT 的实际练习,具体取决于以下步骤:
```java
package io.github.bonigarcia;
......@@ -1701,7 +1701,7 @@ import cucumber.api.java.en.When;
}
```
当然,我们仍然需要实现 JUnit5 测试。为了实现 Cucumber 与 JUnit 5 的集成,Cucumber 扩展需要通过`@ExtendWith(CucumberExtension.class)`在我们班注册。在内部,`CucumberExtension`实现了 Jupiter 扩展模型的`ParameterResolver`回调。目标是将Cucumber特征的相应测试作为 Jupiter`DynamicTest`对象注入测试中。注意,在示例中,`@TestFactory`是如何使用的。
当然,我们仍然需要实现 JUnit5 测试。为了实现 Cucumber 与 JUnit 5 的集成,Cucumber 扩展需要通过`@ExtendWith(CucumberExtension.class)`在我们班注册。在内部,`CucumberExtension`实现了 Jupiter 扩展模型的`ParameterResolver`回调。目标是将 Cucumber 特征的相应测试作为 Jupiter`DynamicTest`对象注入测试中。注意,在示例中,`@TestFactory`是如何使用的。
或者,我们可以用`@CucumberOptions`注释我们的测试类。此注释允许为我们的测试配置 Cumber 设置。此批注允许的元素包括:
......@@ -1743,7 +1743,7 @@ public class CucumberTest {
![](img/00124.gif)
Cucumber和青瓜生产 JUnit 5
Cucumber 和青瓜生产 JUnit 5
# Docker
......
......@@ -24,7 +24,7 @@
在整个软件开发过程中设计和实施测试的时间会导致不同的测试方法,即(见列表后的图表):
* **行为驱动开发****BDD**):在分析阶段开始时,软件消费者(最终用户或客户)和一些开发团队(通常是项目负责人、经理或分析师)之间进行了对话。这些对话用于具体化场景(即,建立对系统功能的共同理解的具体示例)。这些示例构成了使用 Cucumber 等工具开发验收测试的基础(有关更多详细信息,请参阅第 5 章、“JUnit 5 与外部框架的集成”)。BDD 中验收测试的描述(例如,在 Cucumber 中使用Cucumber)生成准确描述应用程序功能的自动化测试和文档。BDD 方法自然地与迭代或敏捷方法相一致,因为预先定义需求非常困难,并且随着团队对项目了解的深入,需求也会不断变化。
* **行为驱动开发****BDD**):在分析阶段开始时,软件消费者(最终用户或客户)和一些开发团队(通常是项目负责人、经理或分析师)之间进行了对话。这些对话用于具体化场景(即,建立对系统功能的共同理解的具体示例)。这些示例构成了使用 Cucumber 等工具开发验收测试的基础(有关更多详细信息,请参阅第 5 章、“JUnit 5 与外部框架的集成”)。BDD 中验收测试的描述(例如,在 Cucumber 中使用 Cucumber)生成准确描述应用程序功能的自动化测试和文档。BDD 方法自然地与迭代或敏捷方法相一致,因为预先定义需求非常困难,并且随着团队对项目了解的深入,需求也会不断变化。
随着 2001 年[敏捷宣言](http://agilemanifesto.org/)的诞生,*敏捷*一词开始普及。它由 17 位软件从业者(肯特·贝克、詹姆斯·格朗宁、罗伯特·C·马丁、迈克·比德尔、吉姆·海史密斯、史蒂夫·梅勒、阿里·范本内库姆、安德鲁·亨特、肯·施瓦伯、阿利斯泰尔·科伯恩、罗恩·杰弗里斯、杰夫·萨瑟兰、沃德·坎宁安、乔恩·克恩、戴夫·托马斯、马丁·福勒和布赖恩·马里克)编写,并包括 12 条原则的列表,用于指导迭代和以人为中心的软件开发过程。基于这些原则,出现了一些软件开发框架,如 SCRUM、看板或极限编程(XP)。
......
+ [零、序言](0.md)
+ [一、软件质量与 Java 测试回顾](1.md)
+ [二、JUnit5 有什么新功能](2.md)
+ [三、JUnit5 标准测试](3.md)
+ [四、使用高级 JUnit 特性简化测试](4.md)
+ [五、JUnit5 与外部框架的集成](5.md)
+ [六、从需求到测试用例](6.md)
+ [七、测试管理](7.md)
+ [精通 JUnit5 软件测试](README.md)
\ No newline at end of file
......@@ -144,7 +144,7 @@ TDD 的主要目标是可测试的代码设计,将测试作为非常有用的
白盒测试几乎总是自动化的,在大多数情况下,采用单元测试的形式。
在实施前进行白盒测试时,采用TDD的形式。
在实施前进行白盒测试时,采用 TDD 的形式。
# 质量检查和质量保证之间的区别
......
......@@ -657,7 +657,7 @@ dependencies {
}
```
Mockito跑过JUnit赛跑者。它为我们创建所有必需的模拟,并通过测试将它们注入类中。有两种基本方法;我们自己实例化 mock,并通过类构造函数或使用一组注释将它们作为类依赖项注入。在下一个示例中,我们将看到如何使用注释来完成。
Mockito 跑过 JUnit 赛跑者。它为我们创建所有必需的模拟,并通过测试将它们注入类中。有两种基本方法;我们自己实例化 mock,并通过类构造函数或使用一组注释将它们作为类依赖项注入。在下一个示例中,我们将看到如何使用注释来完成。
为了让类使用 Mockito 注释,它需要与`MockitoJUnitRunner`一起运行。使用运行器简化了流程,因为您只需向要创建的对象添加注释:
......@@ -780,7 +780,7 @@ public void joeHas5Friends() {
}
```
同样,与Mockito相比几乎没有什么不同,只是 EasyMock 没有间谍。根据上下文的不同,这可能是一个重要的区别。
同样,与 Mockito 相比几乎没有什么不同,只是 EasyMock 没有间谍。根据上下文的不同,这可能是一个重要的区别。
尽管这两个框架相似,但有一些小细节让我们选择 Mockito 作为框架,这将贯穿本书。
......@@ -865,8 +865,8 @@ driver.quit();
```
就这样。我们有一个很小但很有价值的测试来验证一个用例。虽然
关于Selenium还有很多要说的,但希望这能为您
提供足够的信息,让您认识到Selenium背后的潜力。
关于 Selenium 还有很多要说的,但希望这能为您
提供足够的信息,让您认识到 Selenium 背后的潜力。
有关`WebDriver`的更多信息和更复杂的使用,请访问[这里](http://www.seleniumhq.org/)
......@@ -876,7 +876,7 @@ driver.quit();
# Selenide
我们所看到的Selenium是非常酷的。它提供了一个机会,让我们可以了解我们的应用程序是否做得很好,但有时配置和使用起来有点棘手。Selenide 是一个基于 Selenium 的项目,它为编写测试提供了良好的语法,并使测试更具可读性。它对您隐藏了`WebDriver`的用法和配置,同时仍然保持高级别的定制:
我们所看到的 Selenium 是非常酷的。它提供了一个机会,让我们可以了解我们的应用程序是否做得很好,但有时配置和使用起来有点棘手。Selenide 是一个基于 Selenium 的项目,它为编写测试提供了良好的语法,并使测试更具可读性。它对您隐藏了`WebDriver`的用法和配置,同时仍然保持高级别的定制:
1. 与我们迄今为止使用的所有其他库一样,第一步是添加 Gradle 依赖项:
......@@ -886,8 +886,8 @@ dependencies {
}
```
2. 让我们看看如何使用Selenide
编写上一个Selenium测试。对于了解 [JQuery](https://jquery.com/) 的人来说,语法可能很熟悉:
2. 让我们看看如何使用 Selenide
编写上一个 Selenium 测试。对于了解 [JQuery](https://jquery.com/) 的人来说,语法可能很熟悉:
```java
public class SelenideTest {
......@@ -911,7 +911,7 @@ public class SelenideTest {
}
```
这是一种更具表现力的测试方式。除了更流畅的语法之外,在这段代码后面还发生了一些事情,需要额外的 Selenium 行。例如,单击操作将等待相关元素可用,并且只有在预定义的时间段过期时才会失败。另一方面,Selenium会立即失效。在当今世界,许多元素都是通过 JavaScript 动态加载的,我们不能期望所有内容都同时出现。因此,这个 Selenide 特性被证明是有用的,它避免了我们使用重复的样板代码。Selenide还带来了许多其他好处。由于Selenide与Selenium相比所带来的好处,本书将选择它作为我们的框架。此外,还有一整章专门介绍使用该框架的 Web 测试。访问[这里](http://selenide.org/) 了解有关在测试中使用 Web 驱动程序的更多信息。
这是一种更具表现力的测试方式。除了更流畅的语法之外,在这段代码后面还发生了一些事情,需要额外的 Selenium 行。例如,单击操作将等待相关元素可用,并且只有在预定义的时间段过期时才会失败。另一方面,Selenium 会立即失效。在当今世界,许多元素都是通过 JavaScript 动态加载的,我们不能期望所有内容都同时出现。因此,这个 Selenide 特性被证明是有用的,它避免了我们使用重复的样板代码。Selenide 还带来了许多其他好处。由于 Selenide 与 Selenium 相比所带来的好处,本书将选择它作为我们的框架。此外,还有一整章专门介绍使用该框架的 Web 测试。访问[这里](http://selenide.org/) 了解有关在测试中使用 Web 驱动程序的更多信息。
不管测试是用一个框架还是另一个框架编写的,效果都是一样的。测试运行时,会出现 Firefox 浏览器窗口,并按顺序执行测试中定义的所有步骤。除非选择无头浏览器作为您的驱动程序,否则您将能够看到整个测试过程中发生的情况。如果出现问题,可以使用故障跟踪。最重要的是,我们可以在任何时候拍摄浏览器屏幕截图。例如,记录故障时的情况是一种常见做法。
......@@ -1080,7 +1080,7 @@ $> gradle testCucumber
![](img/00ef22c3-dab2-47a2-a9b5-9677e2487c12.png)
Cucumber故事执行报告
Cucumber 故事执行报告
完整的代码示例可以在[存储库中找到](https://bitbucket.org/vfarcic/tdd-java-ch02-example-web)
......
......@@ -299,9 +299,9 @@ JBehave 为我们创建了一个漂亮的报告,并将其放入`target/jbehave
总而言之,在这一点上,我们写了一个有五个场景的故事。这些场景中的每一个都相当于一个规范,该规范将被用作应该开发的定义,并验证开发是否正确完成。这些场景中的每一个都由几个步骤组成,这些步骤定义了先决条件(`Given`)、行动(`When`)和预期结果(`Then`)。
现在是时候在我们的步骤后面编写代码了。然而,在我们开始编码之前,让我们先介绍一下Selenium和Selenide。
现在是时候在我们的步骤后面编写代码了。然而,在我们开始编码之前,让我们先介绍一下 Selenium 和 Selenide。
# SeleniumSelenide
# SeleniumSelenide
Selenium 是一组可用于自动化浏览器的驱动程序。我们可以使用它们操纵浏览器和页面元素,例如,单击按钮或链接,填充表单字段,打开特定的 URL,等等。几乎所有浏览器都有驱动程序,包括 Android、Chrome、FireFox、Internet Explorer、Safari 等。我们最喜欢的是 PhantomJS,它是一种无头浏览器,无需任何 UI 即可工作。使用它运行故事比使用传统浏览器要快,而且我们经常使用它来获得有关 Web 应用程序准备就绪的快速反馈。如果它按预期工作,我们可以继续并在应用程序应该支持的所有不同浏览器和版本中进行尝试。
......@@ -334,7 +334,7 @@ dependencies {
}
```
您已经熟悉了 JUnit 和 JBehave 内核,它们是在前面设置的。两个新添加的元素是Selenide和幻影。刷新渐变依赖项,以便它们包含在 IDEA 项目中。
您已经熟悉了 JUnit 和 JBehave 内核,它们是在前面设置的。两个新添加的元素是 Selenide 和幻影。刷新渐变依赖项,以便它们包含在 IDEA 项目中。
现在,是时候将 PhantomJS`WebDriver`添加到我们的`Steps`类中了:
......
......@@ -61,7 +61,7 @@ TDD 也是如此。我们通过关注小型单元来开发代码。随着我们
# 特征切换示例
下面是我们的演示应用程序。这一次,我们将构建一个简单而小型的**表述性状态转移****REST**)服务,根据需要计算斐波那契序列的具体第`N`项。我们将使用文件跟踪启用/禁用的功能。为了简单起见,我们将使用 Spring Boot 作为我们的选择框架,并将 Thymeleaf 作为模板引擎。这也包含在 SpringBoot依赖项中。有关 Spring Boot 和相关项目的更多信息,请访问[这里](http://projects.spring.io/spring-boot/)。此外,您还可以访问[这里](http://www.thymeleaf.org/) 了解更多有关模板引擎的信息。
下面是我们的演示应用程序。这一次,我们将构建一个简单而小型的**表述性状态转移****REST**)服务,根据需要计算斐波那契序列的具体第`N`项。我们将使用文件跟踪启用/禁用的功能。为了简单起见,我们将使用 Spring Boot 作为我们的选择框架,并将 Thymeleaf 作为模板引擎。这也包含在 SpringBoot 依赖项中。有关 Spring Boot 和相关项目的更多信息,请访问[这里](http://projects.spring.io/spring-boot/)。此外,您还可以访问[这里](http://www.thymeleaf.org/) 了解更多有关模板引擎的信息。
以下是`build.gradle`文件的外观:
......
+ [零、前言](00.md)
+ [一、为什么我应该关心测试驱动的开发?](01.md)
+ [二、工具、框架和环境](02.md)
+ [三、红绿重构——从失败到成功,直到完美](03.md)
+ [四、单元测试——关注你做了什么,而不是已经做了什么](04.md)
+ [五、设计——如果它不可测试,那么它就设计得不好](05.md)
+ [六、Mocking–删除外部依赖项](06.md)
+ [七、TDD 和函数式编程–完美匹配](07.md)
+ [八、BDD–与整个团队合作](08.md)
+ [九、重构遗留代码–使其再次年轻化](09.md)
+ [十、功能切换–将部分完成的功能部署到生产环境](10.md)
+ [十一、把它们放在一起](11.md)
+ [十二、通过实施连续交付利用 TDD](12.md)
+ [Java 测试驱动开发](README.md)
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册