提交 0d23dae8 编写于 作者: W wizardforcel

2021-10-05 23:45:16

上级 3cb60a0b
......@@ -81,7 +81,7 @@ class TestInfoTest {
`TestInfo`对象依赖注入控制台输出
# 重复信息参数 Terresolver
# `RepetitionInfoParameterResolver`
JUnit5 中开箱即用的第二个解析器称为`RepetitionInfoParameterResolver`。给定一个测试类,如果`@RepeatedTest``@BeforeEach``@AfterEach`方法中的方法参数类型为`RepetitionInfo`,则`RepetitionInfoParameterResolver`将提供`RepetitionInfo`的实例。
......@@ -647,13 +647,13 @@ import org.junit.jupiter.params.provider.ValueSource;
}
```
此类的方法(`testWithStrings`定义了一个参数化测试,其中指定了字符串数组。由于注释`@ValueSource`(在本例中为`"Hello"``"World"`中指定了两个字符串参数,测试逻辑将执行两次,每个值一次。此数据使用方法的参数注入测试方法,在本例中,通过名为 argument `String`变量注入。总之,当执行该测试类时,输出如下:
此类的方法(`testWithStrings`定义了一个参数化测试,其中指定了字符串数组。由于注释`@ValueSource`(在本例中为`"Hello"``"World"`中指定了两个字符串参数,测试逻辑将执行两次,每个值一次。此数据使用方法的参数注入测试方法,在本例中,通过名为`argument``String`变量注入。总之,当执行该测试类时,输出如下:
![](img/00078.gif)
使用`@ValueSource`和字符串参数提供程序执行参数化测试
我们还可以在`@ValueSource`注释中使用整数基元类型(`int``long``double`。下面的示例演示了如何。这个示例类的方法(名为`testWithInts``testWithLongs``testWithDoubles`分别使用原语类型 int、long 和 double,使用注释`@ValueSource`以整数值的形式定义参数。为此,需要指定`@ValueSource``ints``longs``doubles`元素:
我们还可以在`@ValueSource`注释中使用整数基元类型(`int``long``double`。下面的示例演示了如何。这个示例类的方法(名为`testWithInts``testWithLongs``testWithDoubles`分别使用原语类型`int``long``double`,使用注释`@ValueSource`以整数值的形式定义参数。为此,需要指定`@ValueSource``ints``longs``doubles`元素:
```java
package io.github.bonigarcia;
......@@ -703,7 +703,7 @@ class ValueSourcePrimitiveTypesParameterizedTest {
注释`@EnumSource`允许指定参数化测试,其中参数源是 Java 枚举类。默认情况下,枚举的每个值都将用于为参数化测试提供数据,每次一个。
例如,在下面的测试类中,方法`testWithEnum`被注释为`@ParameterizedTest``@EnumSource`结合。正如我们所看到的,这个注释的值是`TimeUnit.class`,这是一个标准的 Java 注释(包 Java.util.concurrent),用于表示持续时间。此枚举中定义的可能值为`NANOSECONDS``MICROSECONDS``MILLISECONDS``SECONDS``MINUTES``HOURS``DAYS`
例如,在下面的测试类中,方法`testWithEnum`被注释为`@ParameterizedTest``@EnumSource`结合。正如我们所看到的,这个注释的值是`TimeUnit.class`,这是一个标准的 Java 注释(包`Java.util.concurrent`),用于表示持续时间。此枚举中定义的可能值为`NANOSECONDS``MICROSECONDS``MILLISECONDS``SECONDS``MINUTES``HOURS``DAYS`
```java
package io.github.bonigarcia;
......@@ -962,7 +962,7 @@ class MethodSourcePrimitiveTypesParameterizedTest {
使用`@MethodSource`和原语类型参数提供程序执行参数化测试
最后,关于`@MethodSource`参数化测试,值得一提的是,允许方法提供者返回不同类型(对象或基本类型)的流。这对于真实世界的测试用例非常方便。例如,下面的类实现了一个参数化测试,其中参数提供程序是一个返回混合类型参数的方法:`String``int`。这些参数作为方法参数(在示例中称为 first 和 second)注入测试中。
最后,关于`@MethodSource`参数化测试,值得一提的是,允许方法提供者返回不同类型(对象或基本类型)的流。这对于真实世界的测试用例非常方便。例如,下面的类实现了一个参数化测试,其中参数提供程序是一个返回混合类型参数的方法:`String``int`。这些参数作为方法参数(在示例中称为`first``second`)注入测试中。
```java
package io.github.bonigarcia;
......@@ -999,13 +999,13 @@ class MethodSourceMixedTypesParameterizedTest {
使用具有不同类型参数的`@MethodSource`执行参数化测试
# @CsvSource 和@CsvFileSource
# `@CsvSource`和`@CsvFileSource`
为参数化测试指定参数源的另一种方法是使用逗号分隔值(CSV)。这可以使用注释`@CsvSource`完成,该注释允许将 CSV 内容作为字符串嵌入注释的值中。
考虑下面的例子。它包含一个 Jupiter 参数化测试(名为`testWithCsvSource`,使用注释`@CsvSource`。此批注包含字符串数组。在数组的每个元素中,我们可以看到有一个由逗号分隔的不同值。
CSV 的内容自动转换为字符串和 int。要了解 JUnit 5 在参数中进行的隐式类型转换的更多信息,请参阅本章中的“参数转换”一节。
CSV 的内容自动转换为字符串和`int`。要了解 JUnit 5 在参数中进行的隐式类型转换的更多信息,请参阅本章中的“参数转换”一节。
```java
package io.github.bonigarcia;
......@@ -1290,7 +1290,7 @@ class ExplicitConversionParameterizedTest {
}
```
我们的自定义转换是一个扩展 JUnit5 的`SimpleArgumentConverter`的类。此类重写实际转换发生的 convert 方法。在本例中,我们只需将任何参数源转换为`String`
我们的自定义转换是一个扩展 JUnit5 的`SimpleArgumentConverter`的类。此类重写实际转换发生的`convert`方法。在本例中,我们只需将任何参数源转换为`String`
```java
package io.github.bonigarcia;
......@@ -1315,7 +1315,7 @@ import org.junit.jupiter.params.converter.SimpleArgumentConverter;
JUnit5 中与参数化测试相关的最后一个特性与每次执行测试的显示名称有关。正如我们所了解的,参数化测试通常作为几个单独的测试执行。因此,为了保证可追溯性,最好将每个测试执行与参数源链接起来。
为此,注释`@ParameterizedTest`接受一个名为 name 的元素,我们可以在其中为测试执行指定一个自定义名称(`String`。此外,在这个字符串中,我们可以使用几个内置占位符,如下表所述:
为此,注释`@ParameterizedTest`接受一个名为`name`的元素,我们可以在其中为测试执行指定一个自定义名称(`String`。此外,在这个字符串中,我们可以使用几个内置占位符,如下表所述:
| **占位符** | **说明** |
| --- | --- |
......@@ -1355,7 +1355,7 @@ import org.junit.jupiter.params.provider.CsvSource;
Java 9 于 2017 年 9 月 21 日发布供**通用****GA**)使用。Java9 附带了许多新特性。其中,模块化是 Java9 的定义特性。
到目前为止,Java 中存在一个模块化问题,对于大型代码库来说尤其重要。每个公共类都可以被类路径中的任何其他类访问,从而导致类的意外使用。此外,类路径还存在潜在的问题,例如无法知道是否存在重复的 JAR。为了解决这些问题,Java9 提供了 Java 平台模块系统,它允许创建模块化 JAR 文件。这种类型的模块包含一个名为`module-info.java`的附加模块描述符。这些文件的内容非常简单:它使用关键字 requires 声明对其他模块的依赖关系,并使用关键字`exports`导出自己的包。默认情况下,所有未导出的包都封装在模块中,例如:
到目前为止,Java 中存在一个模块化问题,对于大型代码库来说尤其重要。每个公共类都可以被类路径中的任何其他类访问,从而导致类的意外使用。此外,类路径还存在潜在的问题,例如无法知道是否存在重复的 JAR。为了解决这些问题,Java9 提供了 Java 平台模块系统,它允许创建模块化 JAR 文件。这种类型的模块包含一个名为`module-info.java`的附加模块描述符。这些文件的内容非常简单:它使用关键字`requires`声明对其他模块的依赖关系,并使用关键字`exports`导出自己的包。默认情况下,所有未导出的包都封装在模块中,例如:
```java
module mymodule {
......
此差异已折叠。
......@@ -72,7 +72,7 @@
为了正确地设计测试,我们需要明确定义需要实现什么。为此,重要的是记住测试的一般结构是什么,已经在第 1 章、“软件质量和 Java 测试回顾”中解释过。因此,对于每个测试,我们需要定义:
* 什么是测试夹具,即 SUT 中执行测试所需的状态?这是在测试开始时在称为设置的阶段完成的。在测试结束时,测试夹具可能会在称为拆卸的阶段释放。
* 什么是 SUT,如果我们正在进行单元测试,哪些是它的文档?单元测试应该是独立的,因此我们需要为 DOC 定义替身测试(通常是 mock 或 spie)。
* 什么是 SUT,如果我们正在进行单元测试,哪些是它的文档?单元测试应该是独立的,因此我们需要为 DOC 定义替身测试(通常是模拟或 spie)。
* 这些主张是什么?这是测试的关键部分。如果没有断言,我们就不能声称实际进行了测试。为了设计断言,值得回忆一下它的一般结构。简言之,断言包括一些预期值(测试数据)和从 SUT 获得的实际结果的比较。如果任何断言为否定,测试将被宣布为失败(测试裁决):
![](img/00138.jpeg)
......
......@@ -162,7 +162,7 @@ TDD 的主要目标是可测试的代码设计,将测试作为非常有用的
# 嘲笑
为了让测试快速运行并提供持续的反馈,代码需要以这样一种方式组织:方法、函数和类可以很容易地替换为 mock 和 stub。这种类型的实际代码替换的常用词是**测试替身**。外部依赖性会严重影响执行速度;例如,我们的代码可能需要与数据库通信。通过模仿外部依赖关系,我们能够大幅提高速度。整个单元测试套件的执行应该以分钟为单位,如果不是秒的话。以一种易于模仿和插桩的方式设计代码迫使我们通过应用关注点分离来更好地构建代码。
为了让测试快速运行并提供持续的反馈,代码需要以这样一种方式组织:方法、函数和类可以很容易地替换为模拟和 stub。这种类型的实际代码替换的常用词是**测试替身**。外部依赖性会严重影响执行速度;例如,我们的代码可能需要与数据库通信。通过模仿外部依赖关系,我们能够大幅提高速度。整个单元测试套件的执行应该以分钟为单位,如果不是秒的话。以一种易于模仿和插桩的方式设计代码迫使我们通过应用关注点分离来更好地构建代码。
比速度更重要的是去除外部因素的好处。设置数据库、Web 服务器、外部 API 和代码可能需要的其他依赖项既耗时又不可靠。在许多情况下,这些依赖项甚至可能不可用。例如,我们可能需要创建一个与数据库通信的代码,并让其他人创建一个模式。如果没有 mock,我们将需要等待该模式被设置。
......@@ -216,6 +216,6 @@ BDD 可以为非编码人员提供必要的文档,同时仍然保持 TDD 和
虽然代码设计是主要目标,但在整个 TDD 过程中创建的测试是一项宝贵的资产,应该加以利用,并严重影响我们对传统测试实践的看法。我们经历了最常见的实践,如白盒测试和黑盒测试,试图将它们放到 TDD 的角度,并展示了它们可以相互带来的好处。
您发现 mock 是非常重要的工具,在编写测试时经常是必须的。最后,我们讨论了如何将测试用作可执行文档,以及 TDD 如何减少调试的必要性。
您发现模拟是非常重要的工具,在编写测试时经常是必须的。最后,我们讨论了如何将测试用作可执行文档,以及 TDD 如何减少调试的必要性。
现在我们已经掌握了理论知识,是时候建立开发环境并对不同的测试框架和工具进行概述和比较了。
\ No newline at end of file
......@@ -289,7 +289,7 @@ public void before() {
`@Before`注释指定了将在每个测试方法之前运行的方法。我们可以使用它来设置测试数据,而不用担心之后运行的测试会改变数据的状态。在前面的示例中,我们实例化了`Friendships`类,并向`Friendships`列表中添加了五个示例条目。无论每个单独的测试将执行什么更改,这些数据都将一次又一次地重新创建,直到执行所有测试为止。
使用这两个注释的常见示例是设置数据库数据、创建测试所需的文件等。稍后,我们将看到如何使用 mock 避免外部依赖。然而,功能或集成测试可能仍然需要这些依赖项,`@Before``@BeforeClass`注释是设置它们的好方法。
使用这两个注释的常见示例是设置数据库数据、创建测试所需的文件等。稍后,我们将看到如何使用模拟避免外部依赖。然而,功能或集成测试可能仍然需要这些依赖项,`@Before``@BeforeClass`注释是设置它们的好方法。
一旦建立了数据,我们就可以进行实际测试:
......@@ -538,7 +538,7 @@ gradle test jacocoTestReport
测试使用外部资源或第三方库的代码的常用方法是什么?嘲笑是答案。模拟对象或简单的模拟对象是可以用来替换真实对象的模拟对象。当依赖外部资源的对象被剥夺时,它们非常有用。
事实上,在开发应用程序时根本不需要数据库。相反,您可以使用 mock 来加速开发和测试,并且只在运行时使用真正的数据库连接。我们不必花时间建立数据库和准备测试数据,而可以专注于编写类,并在以后的集成期间考虑它们。
事实上,在开发应用程序时根本不需要数据库。相反,您可以使用模拟来加速开发和测试,并且只在运行时使用真正的数据库连接。我们不必花时间建立数据库和准备测试数据,而可以专注于编写类,并在以后的集成期间考虑它们。
出于演示目的,我们将引入两个新类:`Person`类和`FriendCollection`类,用于表示人员和数据库对象映射。将使用 [MongoDB](https://www.mongodb.org/) 进行持久化。
......@@ -668,14 +668,14 @@ public class FriendshipsTest {
}
```
在您的测试类中,测试类应该用`@InjectMocks`注释。这将告诉 Mockito 要将 mock 注入到哪个类中:
在您的测试类中,测试类应该用`@InjectMocks`注释。这将告诉 Mockito 要将模拟注入到哪个类中:
```java
@InjectMocks
FriendshipsMongo friendships;
```
从那时起,我们可以指定类中的哪些特定方法或对象(在本例中为`FriendshipsMongo`)将被 mock 替换:
从那时起,我们可以指定类中的哪些特定方法或对象(在本例中为`FriendshipsMongo`)将被模拟替换:
```java
@Mock
......@@ -744,7 +744,7 @@ FriendshipsMongo friendships = new FriendshipsMongo();
FriendsCollection friends;
```
`@TestSubject`注释类似于 Mockito 的`@InjectMocks`,而`@Mock`注释表示要以类似于 Mockito 的`@Mock`的方式模拟的对象。此外,类型`NICE`告诉 mock 返回空。
`@TestSubject`注释类似于 Mockito 的`@InjectMocks`,而`@Mock`注释表示要以类似于 Mockito 的`@Mock`的方式模拟的对象。此外,类型`NICE`告诉模拟返回空。
让我们比较一下我们对 Mockito 的一个断言:
......
......@@ -179,7 +179,7 @@ public TicTacToeCollection() throws UnknownHostException {
在实例化`TicTacToeCollection`类时,我们使用指定的 DB 名称(`tic-tac-toe`创建一个新的`MongoCollection`并将其分配给局部变量。
请容忍我们。在我们进入有趣的部分之前,只剩下一个规范了,我们将使用 mock 和 spies。
请容忍我们。在我们进入有趣的部分之前,只剩下一个规范了,我们将使用模拟和 spies。
# 规范–Mongo 集合的名称
......
......@@ -225,7 +225,7 @@ public final void whenAddIsUsedThenItWorks() {
好处:这减少了代码依赖性并且测试执行会更快。
模拟是快速执行测试和集中于单个功能单元的能力的先决条件。通过模拟正在测试的方法外部的依赖关系,开发人员可以专注于手头的任务,而无需花费时间进行设置。在大型团队的情况下,这些依赖关系甚至可能无法开发。此外,没有模拟的测试执行往往很慢。数据库、其他产品、服务等是 mock 的最佳候选对象。
模拟是快速执行测试和集中于单个功能单元的能力的先决条件。通过模拟正在测试的方法外部的依赖关系,开发人员可以专注于手头的任务,而无需花费时间进行设置。在大型团队的情况下,这些依赖关系甚至可能无法开发。此外,没有模拟的测试执行往往很慢。数据库、其他产品、服务等是模拟的最佳候选对象。
使用设置和拆卸方法。
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册