Spring Boot Testing中文文档

本文为官方文档直译版本。原文链接

Spring Boot Testing中文文档

    • 引言
    • 测试范围依赖
    • 测试 Spring 应用程序
    • 测试 Spring Boot 应用程序
      • 检测 Web 应用程序类型
      • 检测测试配置
      • 使用测试配置主方法
      • 排除测试配置
      • 使用应用程序参数
      • 使用模拟环境进行测试
      • 通过运行中的服务器进行测试
      • 自定义 WebTestClient
      • 使用 JMX
      • 使用指标
      • 使用跟踪
      • 模拟和 Spying Beans
      • 自动配置测试
      • 自动配置 JSON 测试
      • 自动配置的 Spring MVC 测试
      • 自动配置 Spring WebFlux 测试
      • 自动配置 Spring GraphQL 测试
      • 自动配置 Data Cassandra 测试
      • 自动配置Data Couchbase 测试
      • 自动配置Data Elasticsearch 测试
      • 自动配置Data JPA 测试
      • 自动配置 JDBC 测试
      • 自动配置Data JDBC 测试
      • 自动配置Data R2DBC 测试
      • 自动配置 jOOQ 测试
      • 自动配置Data MongoDB 测试
      • 自动配置Data Neo4j 测试
      • 自动配置Data Redis 测试
      • 自动配置Data LDAP 测试
      • 自动配置 REST 客户端
      • 自动配置 Spring REST Docs 测试
        • 使用 Mock MVC 自动配置 Spring REST Docs测试
        • 使用 WebTestClient 自动配置 Spring REST Docs测试
        • 使用 REST Assured 自动配置 Spring REST Docs测试
      • 自动配置 Spring Web 服务测试
        • 自动配置 Spring Web 服务客户端测试
        • 自动配置 Spring Web 服务服务器测试
      • 额外的自动配置和切片功能
      • 用户配置和切片
      • 使用 Spock 测试 Spring Boot 应用程序
    • 测试容器
      • 连接服务
      • 动态属性
    • 测试工具
      • ConfigDataApplicationContextInitializer
      • TestPropertyValues
      • OutputCapture
      • TestRestTemplate

引言

Spring Boot 提供了大量实用工具和注解,可在测试应用程序时提供帮助。测试支持由两个模块提供:spring-boot-test 包含核心项目,spring-boot-test-autoconfigure 支持测试的自动配置。
大多数开发人员使用 spring-boot-starter-test “Starter”,它同时导入了 Spring Boot 测试模块以及 JUnit Jupiter、AssertJ、Hamcrest 和其他一些有用的库。

如果有使用 JUnit 4 的测试,可以使用 JUnit 5 的 vintage 引擎来运行它们。要使用 vintage 引擎,请添加对 junit-vintage-engine 的依赖,如下例所示:

<dependency><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.hamcrest</groupId><artifactId>hamcrest-core</artifactId></exclusion></exclusions>
</dependency>

hamcrest-core 排除在外,而使用 spring-boot-starter-test 中的 org.hamcrest:hamcrest

测试范围依赖

spring-boot-starter-test “Starter”(在test``scope内)包含以下提供的库:

  • JUnit 5:Java 应用程序单元测试的事实标准。
  • Spring Test 和 Spring Boot Test: 为 Spring Boot 应用程序提供实用程序和集成测试支持。
  • AssertJ:流畅的断言库。
  • Hamcrest: 一个匹配器对象库(也称为约束或谓词)。
  • Mockito:一个 Java 模拟框架: 一个 Java 模拟框架。
  • JSONassert: 一个 JSON 断言库。
  • JsonPath:JSON 的 XPath: JSON 的 XPath。
  • Awaitility:用于测试异步系统的库: 用于测试异步系统的库。

在编写测试时,我们通常会发现这些常用库非常有用。如果这些库不能满足您的需求,您可以自行添加其他测试依赖库。

测试 Spring 应用程序

依赖注入的一个主要优势是,它可以让你的代码更容易进行单元测试。您可以使用 new 操作符实例化对象,而无需涉及 Spring。您还可以使用模拟对象来代替真实的依赖关系。
通常情况下,你需要超越单元测试,开始集成测试(使用 Spring ApplicationContext)。无需部署应用程序或连接其他基础架构就能执行集成测试是非常有用的。
Spring 框架包含一个专用测试模块,用于此类集成测试。您可以直接向 org.springframework:spring-test 声明依赖关系,或使用 spring-boot-starter-test "Starter "将其临时引入。
如果你以前没有使用过 spring-test 模块,应该先阅读 Spring Framework 参考文档的相关章节。

测试 Spring Boot 应用程序

Spring Boot 应用程序是一个 Spring ApplicationContext,因此除了通常使用普通 Spring 上下文进行测试外,不需要做任何特别的测试。

只有在使用 SpringApplication 创建上下文时,Spring Boot 的外部属性、日志和其他功能才会默认安装在上下文中。

Spring Boot 提供了 @SpringBootTest 注解,当你需要 Spring Boot 功能时,可以用它来替代标准的 spring-test @ContextConfiguration 注解。该注解的工作原理是通过 SpringApplication 创建测试中使用的 ApplicationContext。除了 @SpringBootTest 之外,还提供了许多其他注解,用于测试应用程序的更多特定片段。

如果使用的是 JUnit 4,请不要忘记在测试中添加 @RunWith(SpringRunner.class),否则注解将被忽略。如果使用的是 JUnit 5,则无需添加 @ExtendWith(SpringExtension.class),因为 @SpringBootTest 和其他 @...Test 注释都已使用了该注解。

默认情况下,@SpringBootTest 不会启动服务器。你可以使用 @SpringBootTestwebEnvironment 属性来进一步完善测试的运行方式:

  • MOCK(默认): 加载网络 ApplicationContext 并提供模拟网络环境。使用此注解时,不会启动嵌入式服务器。如果classpath 上没有网络环境,该模式会透明地退回到创建普通的非网络 ApplicationContext。它可与 @AutoConfigureMockMvc@AutoConfigureWebTestClient 结合使用,用于对网络应用程序进行基于模拟的测试。
  • RANDOM_PORT:加载 WebServerApplicationContext 并提供真实的网络环境。嵌入式服务器会启动并监听一个随机端口。
  • DEFINED_PORT:加载 WebServerApplicationContext 并提供真实的网络环境。嵌入式服务器将被启动,并监听一个已定义的端口(application.properties)或默认的 8080 端口。
  • NONE: 使用 SpringApplication 加载 ApplicationContext,但不提供任何网络环境(模拟或其他)。

如果您的测试是 @Transactional,那么默认情况下,它会在每个测试方法结束时回滚事务。不过,由于使用 RANDOM_PORTDEFINED_PORT 会隐式地提供一个真正的 servlet 环境,HTTP 客户端和服务器会在不同的线程中运行,因此也会在不同的事务中运行。在这种情况下,服务器上启动的任何事务都不会回滚。

@SpringBootTest 设置 webEnvironment = WebEnvironment.RANDOM_PORT 还会在一个单独的随机端口上启动管理服务器,如果你的应用程序为管理服务器使用了不同的端口的话。

检测 Web 应用程序类型

如果有 Spring MVC,则会配置基于 MVC 的常规应用上下文。如果只有 Spring WebFlux,我们会检测到并配置基于 WebFlux 的应用上下文。
如果两者都存在,则以 Spring MVC 为优先。如果想在这种情况下测试反应式 Web 应用程序,则必须设置 spring.main.web-application-type 属性:

import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest(properties = "spring.main.web-application-type=reactive")
class MyWebFluxTests {// ...}

检测测试配置

如果您熟悉 Spring 测试框架,可能会习惯使用 @ContextConfiguration(classes=...) 来指定要加载的 Spring @Configuration。另外,您可能经常在测试中使用嵌套的 @Configuration 类。
在测试 Spring Boot 应用程序时,通常不需要这样做。只要您没有明确定义,Spring Boot 的 @*Test 注解就会自动搜索您的主配置。
搜索算法会从包含测试的包开始往上搜索,直到找到注释为 @SpringBootApplication@SpringBootConfiguration 的类为止。只要代码结构合理,通常就能找到主配置。

如果使用测试注解来测试应用程序的特定切片,则应避免在主方法的应用程序类上添加针对特定区域的配置设置。
@SpringBootApplication 的底层组件扫描配置定义了排除过滤器,用于确保切片工作符合预期。如果你在@SpringBootApplication注释的类中使用了显式@ComponentScan指令,请注意这些过滤器将被禁用。如果正在使用切片功能,则应重新定义它们。

如果要自定义主配置,可以使用嵌套的 @TestConfiguration 类。与嵌套的 @Configuration 类不同的是,嵌套的 @TestConfiguration 类是应用程序主配置的补充。

Spring 的测试框架会在测试之间缓存应用程序上下文。因此,只要你的测试共享相同的配置(无论配置是如何被发现的),加载上下文这一可能耗时的过程就只会发生一次。

使用测试配置主方法

通常情况下,@SpringBootTest发现的测试配置将是你的主@SpringBootApplication。在大多数结构良好的应用程序中,该配置类还将包括用于启动应用程序的主方法。
例如,以下是典型 Spring Boot 应用程序的常见代码模式:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class MyApplication {public static void main(String[] args) {SpringApplication.run(MyApplication.class, args);}}

在上面的示例中,main 方法除了委托 SpringApplication.run 以外没有做任何其他事情。不过,也可以使用更复杂的 main 方法,在调用 SpringApplication.run 之前应用自定义功能。
例如,下面是一个更改横幅模式和设置附加配置文件的应用程序:

import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class MyApplication {public static void main(String[] args) {SpringApplication application = new SpringApplication(MyApplication.class);application.setBannerMode(Banner.Mode.OFF);application.setAdditionalProfiles("myprofile");application.run(args);}}

由于main方法中的自定义会影响生成的ApplicationContext,所以你也可能想使用main方法来创建测试中使用的ApplicationContext。默认情况下,@SpringBootTest 不会调用主方法,而是直接使用类本身来创建 ApplicationContext
如果想改变这种行为,可以将 @SpringBootTestuseMainMethod 属性改为 UseMainMethod.ALWAYSUseMainMethod.WHEN_AVAILABLE。当设置为 ALWAYS 时,如果找不到主方法,测试就会失败。设置为 WHEN_AVAILABLE 时,如果主方法可用,则将使用该方法,否则将使用标准加载机制。
例如,下面的测试将调用 MyApplication 的主方法来创建 ApplicationContext。如果主方法设置了附加配置文件,那么这些配置文件将在 ApplicationContext 启动时处于活动状态。

import org.junit.jupiter.api.Test;import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.UseMainMethod;@SpringBootTest(useMainMethod = UseMainMethod.ALWAYS)
class MyApplicationTests {@Testvoid exampleTest() {// ...}}

排除测试配置

如果你的应用程序使用了组件扫描(例如,如果你使用了 @SpringBootApplication@ComponentScan),你可能会发现只为特定测试创建的顶级配置类不小心被到处收集。
正如我们前面所看到的,@TestConfiguration 可用于测试的内部类,以自定义主要配置。@TestConfiguration 也可用于顶层类。这样做表示该类不应被扫描选中。然后,您可以在需要的地方显式导入该类,如下例所示:

import org.junit.jupiter.api.Test;import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;@SpringBootTest
@Import(MyTestsConfiguration.class)
class MyTests {@Testvoid exampleTest() {// ...}}

如果直接使用 @ComponentScan(即不通过 @SpringBootApplication),则需要注册 TypeExcludeFilter。详情请参见 Javadoc。

导入的 @TestConfiguration 比内类的 @TestConfiguration 处理得更早,而且导入的 @TestConfiguration 将在通过组件扫描发现的任何配置之前被处理。一般来说,这种排序上的差异不会产生明显的影响,但如果您依赖 bean 重载,则需要注意这一点。

使用应用程序参数

如果应用程序需要参数,可以让 @SpringBootTest 使用 args 属性注入参数。

import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.test.context.SpringBootTest;import static org.assertj.core.api.Assertions.assertThat;@SpringBootTest(args = "--app.test=one")
class MyApplicationArgumentTests {@Testvoid applicationArgumentsPopulated(@Autowired ApplicationArguments args) {assertThat(args.getOptionNames()).containsOnly("app.test");assertThat(args.getOptionValues("app.test")).containsOnly("one");}}

使用模拟环境进行测试

默认情况下,@SpringBootTest 不会启动服务器,而是为测试 Web 端点设置一个模拟环境。
使用 Spring MVC,我们可以使用 [MockMvc](https://docs.spring.io/spring-framework/reference/testing/spring-mvc-test-framework.html)WebTestClient 查询网络端点,如下例所示:

import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.test.web.servlet.MockMvc;import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;@SpringBootTest
@AutoConfigureMockMvc
class MyMockMvcTests {@Testvoid testWithMockMvc(@Autowired MockMvc mvc) throws Exception {mvc.perform(get("/")).andExpect(status().isOk()).andExpect(content().string("Hello World"));}// If Spring WebFlux is on the classpath, you can drive MVC tests with a WebTestClient@Testvoid testWithWebTestClient(@Autowired WebTestClient webClient) {webClient.get().uri("/").exchange().expectStatus().isOk().expectBody(String.class).isEqualTo("Hello World");}}

如果只想关注网络层而不想启动完整的 ApplicationContext,可以考虑使用 @WebMvcTest 代替。

通过 Spring WebFlux 端点,您可以使用 [WebTestClient](https://docs.spring.io/spring-framework/reference/testing/webtestclient.html),如下例所示:

import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.reactive.server.WebTestClient;@SpringBootTest
@AutoConfigureWebTestClient
class MyMockWebTestClientTests {@Testvoid exampleTest(@Autowired WebTestClient webClient) {webClient.get().uri("/").exchange().expectStatus().isOk().expectBody(String.class).isEqualTo("Hello World");}}

在模拟环境中进行测试通常比使用完整的 servlet 容器运行更快。不过,由于模拟发生在 Spring MVC 层,因此依赖于低层 servlet 容器行为的代码无法直接使用 MockMvc 进行测试。
例如,Spring Boot 的错误处理基于 servlet 容器提供的 "错误页面 "支持。这意味着,虽然您可以测试 MVC 层是否按预期抛出和处理异常,但却无法直接测试是否渲染了特定的自定义错误页面。如果需要测试这些较低层次的问题,可以按照下一节所述启动一个完全运行的服务器。

通过运行中的服务器进行测试

如果需要启动一个完整运行的服务器,建议使用随机端口。如果使用 @SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT),每次测试运行时都会随机选择一个可用端口。
@LocalServerPort 注解可用于在测试中注入实际使用的端口。为方便起见,需要对已启动的服务器进行 REST 调用的测试可以额外 @Autowire 一个 WebTestClient,它可以解析到运行服务器的相对链接,并带有专用的 API 来验证响应,如下例所示:

import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.test.web.reactive.server.WebTestClient;@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class MyRandomPortWebTestClientTests {@Testvoid exampleTest(@Autowired WebTestClient webClient) {webClient.get().uri("/").exchange().expectStatus().isOk().expectBody(String.class).isEqualTo("Hello World");}}

通过使用 @AutoConfigureWebTestClient 对测试类进行注解,WebTestClient 还可以与模拟环境一起使用,从而无需运行服务器。

此设置需要在类路径上添加 spring-webflux。如果不能或不愿添加 webflux,Spring Boot 还提供了 TestRestTemplate 工具:

import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.client.TestRestTemplate;import static org.assertj.core.api.Assertions.assertThat;@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class MyRandomPortTestRestTemplateTests {@Testvoid exampleTest(@Autowired TestRestTemplate restTemplate) {String body = restTemplate.getForObject("/", String.class);assertThat(body).isEqualTo("Hello World");}}

自定义 WebTestClient

要自定义 WebTestClient Bean,请配置 WebTestClientBuilderCustomizer Bean。任何此类 Bean 都会被用于创建 WebTestClientWebTestClient.Builder 调用。

使用 JMX

由于测试上下文框架会缓存上下文,因此默认情况下会禁用 JMX,以防止相同组件在同一域上注册。如果此类测试需要访问 MBeanServer,请考虑将其也标记为 dirty:

import javax.management.MBeanServer;import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.DirtiesContext;import static org.assertj.core.api.Assertions.assertThat;@SpringBootTest(properties = "spring.jmx.enabled=true")
@DirtiesContext
class MyJmxTests {@Autowiredprivate MBeanServer mBeanServer;@Testvoid exampleTest() {assertThat(this.mBeanServer.getDomains()).contains("java.lang");// ...}}

使用指标

在使用 @SpringBootTest 时,无论你的类路径如何,除了内存备份外,度量表注册表都不会自动配置。
如果需要将指标导出到不同的后端作为集成测试的一部分,请使用 @AutoConfigureObservability 进行注释。

使用跟踪

使用 @SpringBootTest 时,无论你的类路径如何,报告数据的跟踪组件都不会自动配置。
如果需要将这些组件作为集成测试的一部分,请使用 @AutoConfigureObservability 对测试进行注释。
如果你创建了自己的报告组件(例如自定义 SpanExporterSpanHandler),并且不想让它们在测试中激活,可以使用 @ConditionalOnEnabledTracing 注解来禁用它们。

模拟和 Spying Beans

运行测试时,有时需要在应用程序上下文中模拟某些组件。例如,您可能会在某个远程服务上设置一个门面,而该服务在开发过程中是不可用的。当您想模拟在真实环境中很难触发的故障时,模拟也很有用。
Spring Boot 包含一个 @MockBean 注解,可用于为 ApplicationContext 中的 Bean 定义 Mockito mock。您可以使用注解添加新的 Bean 或替换现有的 Bean 定义。该注解可直接用于测试类、测试中的字段或 @Configuration 类和字段。在字段上使用时,创建的模拟实例也会被注入。每次测试方法结束后,模拟 bean 都会自动重置。

如果您的测试使用了 Spring Boot 的测试注解之一(如 @SpringBootTest),该功能就会自动启用。要在不同的安排下使用此功能,必须显式添加监听器,如下例所示:

import org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener;
import org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;@ContextConfiguration(classes = MyConfig.class)
@TestExecutionListeners({ MockitoTestExecutionListener.class, ResetMocksTestExecutionListener.class })
class MyTests {// ...}

下面的示例用一个模拟实现替换了现有的 RemoteService Bean:

import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;@SpringBootTest
class MyTests {@Autowiredprivate Reverser reverser;@MockBeanprivate RemoteService remoteService;@Testvoid exampleTest() {given(this.remoteService.getValue()).willReturn("spring");String reverse = this.reverser.getReverseValue(); // Calls injected RemoteServiceassertThat(reverse).isEqualTo("gnirps");}}

@MockBean 不能用于模拟在应用程序上下文刷新期间执行的 Bean 行为。执行测试时,应用程序上下文刷新已经完成,来不及配置模拟行为。在这种情况下,我们建议使用 @Bean 方法来创建和配置模拟。

此外,您还可以使用 @SpyBean 用 Mockito spy 封装任何现有 Bean。详情请参见 Javadoc。

Spring 的测试框架会在测试之间缓存应用程序上下文,并为共享相同配置的测试重用上下文,但 @MockBean@SpyBean 的使用会影响缓存键,这很可能会增加上下文的数量。

如果您使用 @SpyBean 来监视带有 @Cacheable 方法的 Bean,而这些方法会通过名称引用参数,那么您的应用程序在编译时必须使用 -parameters。这样可以确保一旦 Bean 被监视,缓存基础架构就可以使用参数名称。

当您使用 @SpyBean 监视由 Spring 代理的 Bean 时,您可能需要在某些情况下移除 Spring 的代理,例如在使用 givenwhen 设置期望值时。请使用 AopTestUtils.getTargetObject(yourProxiedSpy) 来移除代理。

自动配置测试

Spring Boot 的自动配置系统在应用程序中运行良好,但有时对测试来说可能有点太多。通常只加载测试应用程序 "片段 "所需的配置部分会有帮助。例如,您可能想测试 Spring MVC 控制器是否正确映射了 URL,而您不想在这些测试中涉及数据库调用,或者您可能想测试 JPA 实体,而您对这些测试运行时的 Web 层不感兴趣。
spring-boot-test-autoconfigure 模块包含大量注解,可用于自动配置此类 “切片”。每个注解的工作方式类似,都提供了一个用于加载 ApplicationContext@...Test 注解,以及一个或多个用于自定义自动配置设置的 @AutoConfigure...annotation 注解。

每个片段都会将组件扫描限制在适当的组件上,并加载一组非常有限的自动配置类。如果需要排除其中一个,大多数 @...Test 注解都提供了一个 excludeAutoConfiguration 属性。或者,您也可以使用 @ImportAutoConfiguration#exclude

不支持在一个测试中使用多个 @...Test 注释来包含多个 “片段”。如果需要多个 “片段”,请选择其中一个 @...Test 注释,然后手工添加其他 "片段 "的 @AutoConfigure...annotations

也可以将 @AutoConfigure... 注解与标准的 @SpringBootTest 注解结合使用。如果你对 "切分 "应用程序不感兴趣,但又想要一些自动配置的测试 Bean,那么就可以使用这种组合。

自动配置 JSON 测试

要测试对象 JSON 序列化和反序列化是否按预期运行,可以使用 @JsonTest 注解。@JsonTest 会自动配置可用的受支持 JSON 映射器,该映射器可以是以下库之一:

  • Jackson ObjectMapper、任何 @JsonComponent Bean 和任何 Jackson 模块
  • Gson
  • Jsonb

@JsonTest 启用的自动配置列表见附录。

如果需要配置自动配置的元素,可以使用 @AutoConfigureJsonTesters 注解。
Spring Boot 包含基于 AssertJ 的帮助程序,可与 JSONAssert 和 JsonPath 库配合使用,检查 JSON 是否按预期显示。JacksonTesterGsonTesterJsonbTesterBasicJsonTester 类可分别用于 Jackson、Gson、Jsonb 和 Strings。使用 @JsonTest 时,测试类上的任何辅助字段都可以 @Autowired。下面的示例展示了一个用于 Jackson 的测试类:

import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.json.JsonTest;
import org.springframework.boot.test.json.JacksonTester;import static org.assertj.core.api.Assertions.assertThat;@JsonTest
class MyJsonTests {@Autowiredprivate JacksonTester<VehicleDetails> json;@Testvoid serialize() throws Exception {VehicleDetails details = new VehicleDetails("Honda", "Civic");// Assert against a `.json` file in the same package as the testassertThat(this.json.write(details)).isEqualToJson("expected.json");// Or use JSON path based assertionsassertThat(this.json.write(details)).hasJsonPathStringValue("@.make");assertThat(this.json.write(details)).extractingJsonPathStringValue("@.make").isEqualTo("Honda");}@Testvoid deserialize() throws Exception {String content = "{\"make\":\"Ford\",\"model\":\"Focus\"}";assertThat(this.json.parse(content)).isEqualTo(new VehicleDetails("Ford", "Focus"));assertThat(this.json.parseObject(content).getMake()).isEqualTo("Ford");}}

JSON 辅助类也可直接用于标准单元测试。为此,如果不使用 @JsonTest,请在 @Before 方法中调用辅助类的 initFields 方法。

如果您使用 Spring Boot 基于 AssertJ 的助手来断言给定 JSON 路径上的数字值,根据类型的不同,您可能无法使用 isEqualTo。相反,您可以使用 AssertJ 的 satisfies 来断言该值符合给定条件。例如,下面的示例断言实际数字是一个接近 0.15 的浮点数值,偏移量为 0.01

@Test
void someTest() throws Exception {SomeObject value = new SomeObject(0.152f);assertThat(this.json.write(value)).extractingJsonPathNumberValue("@.test.numberValue").satisfies((number) -> assertThat(number.floatValue()).isCloseTo(0.15f, within(0.01f)));
}

自动配置的 Spring MVC 测试

要测试 Spring MVC 控制器是否按预期运行,请使用 @WebMvcTest 注解。@WebMvcTest 会自动配置 Spring MVC 基础架构,并将扫描的 Bean 限制为 @Controller@ControllerAdvice@JsonComponentConverterGenericConverterFilterHandlerInterceptorWebMvcConfigurerWebMvcRegistrationsHandlerMethodArgumentResolver。使用 @WebMvcTest 注解时,常规的 @Component@ConfigurationProperties Bean 不会被扫描。@EnableConfigurationProperties 可用于包含 @ConfigurationProperties Bean。

@WebMvcTest 启用的自动配置设置列表见附录。

如果需要注册额外的组件(如 Jackson 模块),可以通过在测试中使用 @Import 来导入额外的配置类。

通常,@WebMvcTest 仅限于单个控制器,并与 @MockBean 结合使用,为所需的协作者提供模拟实现。
@WebMvcTest 还能自动配置 MockMvc。Mock MVC 为快速测试 MVC 控制器提供了一种强大的方法,而无需启动完整的 HTTP 服务器。

你也可以在非@WebMvcTest(如 @SpringBootTest)中自动配置 MockMvc,方法是用 @AutoConfigureMockMvc 对其进行注解。下面的示例使用了 MockMvc:

import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;@WebMvcTest(UserVehicleController.class)
class MyControllerTests {@Autowiredprivate MockMvc mvc;@MockBeanprivate UserVehicleService userVehicleService;@Testvoid testExample() throws Exception {given(this.userVehicleService.getVehicleDetails("sboot")).willReturn(new VehicleDetails("Honda", "Civic"));this.mvc.perform(get("/sboot/vehicle").accept(MediaType.TEXT_PLAIN)).andExpect(status().isOk()).andExpect(content().string("Honda Civic"));}}

如果需要配置自动配置的元素(例如,何时应用 servlet 过滤器),可以使用 @AutoConfigureMockMvc 注解中的属性。

如果使用 HtmlUnit 和 Selenium,自动配置还会提供一个 HtmlUnit WebClient Bean 和/或 Selenium WebDriver Bean。下面的示例使用了 HtmlUnit:

import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;@WebMvcTest(UserVehicleController.class)
class MyHtmlUnitTests {@Autowiredprivate WebClient webClient;@MockBeanprivate UserVehicleService userVehicleService;@Testvoid testExample() throws Exception {given(this.userVehicleService.getVehicleDetails("sboot")).willReturn(new VehicleDetails("Honda", "Civic"));HtmlPage page = this.webClient.getPage("/sboot/vehicle.html");assertThat(page.getBody().getTextContent()).isEqualTo("Honda Civic");}}

默认情况下,Spring Boot 会将 WebDriver Bean 放在一个特殊的 "作用域 "中,以确保驱动程序在每次测试后退出,并注入一个新实例。如果不希望出现这种行为,可以在 WebDriver @Bean 定义中添加 @Scope("singleton")

Spring Boot 创建的 WebDriver 作用域将取代任何用户定义的同名作用域。如果您定义了自己的 WebDriver 作用域,可能会发现它在使用 @WebMvcTest 时停止工作。

如果类路径上有 Spring Security,@WebMvcTest 也会扫描 WebSecurityConfigurer Bean。你可以使用 Spring Security 的测试支持,而不是完全禁用此类测试的安全性。有关如何使用 Spring Security 的 MockMvc 支持的更多详情,请参阅 [howto.html](https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto.testing.with-spring-security) 如何使用部分。

有时,仅编写 Spring MVC 测试是不够的;Spring Boot 可以帮助您使用实际服务器运行完整的端到端测试。

自动配置 Spring WebFlux 测试

要测试 Spring WebFlux 控制器是否按预期运行,可以使用 @WebFluxTest 注解。@WebFluxTest 会自动配置 Spring WebFlux 基础架构,并将扫描的 Bean 限制为 @Controller@ControllerAdvice@JsonComponentConverterGenericConverterWebFilterWebFluxConfigurer。使用 @WebFluxTest 注解时,常规的 @Component@ConfigurationProperties Bean 不会被扫描。@EnableConfigurationProperties 可用于包含 @ConfigurationProperties Bean。

@WebFluxTest 启用的自动配置列表见附录。

如果需要注册额外的组件(如 Jackson 模块),可以使用 @Import 在测试中导入额外的配置类。

通常,@WebFluxTest 仅限于单个控制器,并与 @MockBean 注解结合使用,为所需的协作者提供模拟实现。
@WebFluxTest 还能自动配置 [WebTestClient](https://docs.spring.io/spring-framework/reference/testing/webtestclient.html),这为快速测试 WebFlux 控制器提供了一种强大的方式,而无需启动完整的 HTTP 服务器。

你也可以在非 @WebFluxTest(如 @SpringBootTest)中自动配置 WebTestClient,方法是用 @AutoConfigureWebTestClient 对其进行注解。下面的示例展示了一个同时使用 @WebFluxTestWebTestClient 的类:

import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.web.reactive.server.WebTestClient;import static org.mockito.BDDMockito.given;@WebFluxTest(UserVehicleController.class)
class MyControllerTests {@Autowiredprivate WebTestClient webClient;@MockBeanprivate UserVehicleService userVehicleService;@Testvoid testExample() {given(this.userVehicleService.getVehicleDetails("sboot")).willReturn(new VehicleDetails("Honda", "Civic"));this.webClient.get().uri("/sboot/vehicle").accept(MediaType.TEXT_PLAIN).exchange().expectStatus().isOk().expectBody(String.class).isEqualTo("Honda Civic");}}

目前只有 WebFlux 应用程序支持这种设置,因为在模拟网络应用程序中使用 WebTestClient 只能与 WebFlux 配合使用。

@WebFluxTest 无法检测通过功能性 Web 框架注册的路由。若要在上下文中测试 RouterFunction Bean,可考虑使用 @Import@SpringBootTest 自行导入 RouterFunction

@WebFluxTest 无法检测注册为 SecurityWebFilterChain 类型的 @Bean 的自定义安全配置。要将其纳入测试,需要使用 @Import@SpringBootTest 来导入注册 Bean 的配置。

有时,仅仅编写 Spring WebFlux 测试是不够的;Spring Boot 可以帮助您使用实际服务器运行完整的端到端测试。

自动配置 Spring GraphQL 测试

Spring GraphQL 提供专门的测试支持模块;您需要将其添加到您的项目中:

<dependencies><dependency><groupId>org.springframework.graphql</groupId><artifactId>spring-graphql-test</artifactId><scope>test</scope></dependency><!-- Unless already present in the compile scope --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId><scope>test</scope></dependency>
</dependencies>
dependencies {testImplementation("org.springframework.graphql:spring-graphql-test")// Unless already present in the implementation configurationtestImplementation("org.springframework.boot:spring-boot-starter-webflux")
}

该测试模块包含 GraphQlTester。测试中会大量使用该测试器,因此请务必熟悉使用。GraphQlTester 有多种变体,Spring Boot 会根据测试类型自动配置它们:

  • ExecutionGraphQlServiceTester 在服务器端执行测试,没有客户端,也没有传输工具
  • HttpGraphQlTester 使用连接到服务器的客户端执行测试,无论是否有实时服务器

通过 @GraphQlTest 注解,Spring Boot 可以帮助您测试 Spring GraphQL 控制器。@GraphQlTest 会自动配置 Spring GraphQL 基础架构,而不涉及任何传输或服务器。这将扫描的 Bean 限制为 @ControllerRuntimeWiringConfigurerJsonComponentConverterGenericConverterDataFetcherExceptionResolverInstrumentationGraphQlSourceBuilderCustomizer。当使用 @GraphQlTest 注解时,常规的 @Component@ConfigurationProperties Bean 不会被扫描。@EnableConfigurationProperties 可用于包含 @ConfigurationProperties Bean。

@GraphQlTest 启用的自动配置列表见附录。

通常,@GraphQlTest 仅限于一组控制器,并与 @MockBean 注解结合使用,为所需的协作器提供模拟实现。

import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.docs.web.graphql.runtimewiring.GreetingController;
import org.springframework.boot.test.autoconfigure.graphql.GraphQlTest;
import org.springframework.graphql.test.tester.GraphQlTester;@GraphQlTest(GreetingController.class)
class GreetingControllerTests {@Autowiredprivate GraphQlTester graphQlTester;@Testvoid shouldGreetWithSpecificName() {this.graphQlTester.document("{ greeting(name: \"Alice\") } ").execute().path("greeting").entity(String.class).isEqualTo("Hello, Alice!");}@Testvoid shouldGreetWithDefaultName() {this.graphQlTester.document("{ greeting } ").execute().path("greeting").entity(String.class).isEqualTo("Hello, Spring!");}}

@SpringBootTest 测试是完全集成测试,涉及整个应用程序。使用随机端口或定义端口时,会配置一个实时服务器,并自动生成一个 HttpGraphQlTester Bean,以便使用它来测试服务器。当配置了 MOCK 环境时,您也可以用 @AutoConfigureHttpGraphQlTester 对测试类进行注解,从而请求一个 HttpGraphQlTester Bean:

import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.graphql.tester.AutoConfigureHttpGraphQlTester;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.graphql.test.tester.HttpGraphQlTester;@AutoConfigureHttpGraphQlTester
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
class GraphQlIntegrationTests {@Testvoid shouldGreetWithSpecificName(@Autowired HttpGraphQlTester graphQlTester) {HttpGraphQlTester authenticatedTester = graphQlTester.mutate().webTestClient((client) -> client.defaultHeaders((headers) -> headers.setBasicAuth("admin", "ilovespring"))).build();authenticatedTester.document("{ greeting(name: \"Alice\") } ").execute().path("greeting").entity(String.class).isEqualTo("Hello, Alice!");}}

自动配置 Data Cassandra 测试

您可以使用 @DataCassandraTest 测试 Cassandra 应用程序。默认情况下,它会配置 CassandraTemplate、扫描 @Table 类并配置 Spring Data Cassandra 资源库。使用 @DataCassandraTest 注解时,不会扫描常规的 @Component@ConfigurationProperties Bean。@EnableConfigurationProperties 可用于包含 @ConfigurationProperties Bean。(有关在 Spring Boot 中使用 Cassandra 的更多信息,请参阅 “data.html”)。

@DataCassandraTest 启用的自动配置设置列表见附录。

下面的示例展示了在 Spring Boot 中使用 Cassandra 测试的典型设置:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.cassandra.DataCassandraTest;@DataCassandraTest
class MyDataCassandraTests {@Autowiredprivate SomeRepository repository;}

自动配置Data Couchbase 测试

您可以使用 @DataCouchbaseTest 测试 Couchbase 应用程序。默认情况下,它会配置 CouchbaseTemplateReactiveCouchbaseTemplate、扫描 @Document 类并配置 Spring Data Couchbase 存储库。使用 @DataCouchbaseTest 注解时,不会扫描常规的 @Component@ConfigurationProperties Bean。@EnableConfigurationProperties 可用于包含 @ConfigurationProperties Bean。(有关在 Spring Boot 中使用 Couchbase 的更多信息,请参阅本章前面的 “data.html”)。

@DataCouchbaseTest 启用的自动配置设置列表见附录。

下面的示例展示了在 Spring Boot 中使用 Couchbase 测试的典型设置:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.couchbase.DataCouchbaseTest;@DataCouchbaseTest
class MyDataCouchbaseTests {@Autowiredprivate SomeRepository repository;// ...}

自动配置Data Elasticsearch 测试

您可以使用 @DataElasticsearchTest 测试 Elasticsearch 应用程序。默认情况下,它会配置 ElasticsearchRestTemplate、扫描 @Document 类并配置 Spring Data Elasticsearch 资源库。使用 @DataElasticsearchTest 注解时,不会扫描常规的 @Component@ConfigurationProperties Bean。@EnableConfigurationProperties 可用于包含 @ConfigurationProperties Bean。(有关在 Spring Boot 中使用 Elasticsearch 的更多信息,请参阅本章前面的 “data.html”)。

@DataElasticsearchTest 启用的自动配置设置列表见附录。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.elasticsearch.DataElasticsearchTest;@DataElasticsearchTest
class MyDataElasticsearchTests {@Autowiredprivate SomeRepository repository;// ...}

自动配置Data JPA 测试

您可以使用 @DataJpaTest 注解来测试 JPA 应用程序。默认情况下,它会扫描 @Entity 类并配置 Spring Data JPA 资源库。如果类路径上有嵌入式数据库,它也会配置一个。通过将 spring.jpa.show-sql 属性设置为 true,默认情况下会记录 SQL 查询。可以使用注解的 showSql 属性禁用此功能。
使用 @DataJpaTest 注解时不会扫描常规 @Component@ConfigurationProperties Bean。@EnableConfigurationProperties 可用于包含 @ConfigurationProperties Bean。

@DataJpaTest 启用的自动配置设置列表见附录。

默认情况下,数据 JPA 测试是事务性的,并在每次测试结束时回滚。详情请参见 Spring Framework 参考文档中的相关章节。如果这不是你想要的,你可以为某个测试或整个类禁用事务管理,方法如下:

import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;@DataJpaTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
class MyNonTransactionalTests {// ...}

数据 JPA 测试还可以注入 [TestEntityManager](https://github.com/spring-projects/spring-boot/tree/v3.2.0/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/orm/jpa/TestEntityManager.java) Bean,它提供了标准 JPA EntityManager 的替代方案,是专门为测试设计的。

TestEntityManager 也可以通过添加 @AutoConfigureTestEntityManager 自动配置到任何基于 Spring 的测试类中。这样做时,请确保您的测试在事务中运行,例如在测试类或方法中添加 @Transactional

如果需要,还可以使用 JdbcTemplate。下面的示例展示了 @DataJpaTest 注解的使用:

import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;import static org.assertj.core.api.Assertions.assertThat;@DataJpaTest
class MyRepositoryTests {@Autowiredprivate TestEntityManager entityManager;@Autowiredprivate UserRepository repository;@Testvoid testExample() {this.entityManager.persist(new User("sboot", "1234"));User user = this.repository.findByUsername("sboot");assertThat(user.getUsername()).isEqualTo("sboot");assertThat(user.getEmployeeNumber()).isEqualTo("1234");}}

内存嵌入式数据库通常非常适合测试,因为它们速度快,而且不需要安装。不过,如果您更喜欢针对真实数据库运行测试,则可以使用 @AutoConfigureTestDatabase 注解,如下例所示:

import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;@DataJpaTest
@AutoConfigureTestDatabase(replace = Replace.NONE)
class MyRepositoryTests {// ...}

自动配置 JDBC 测试

@JdbcTest@DataJpaTest 类似,但适用于只需要数据源而不使用 Spring Data JDBC 的测试。默认情况下,它会配置一个内存嵌入式数据库和一个 JdbcTemplate。使用 @JdbcTest 注解时,不会扫描常规的 @Component@ConfigurationProperties Bean。@EnableConfigurationProperties 可用于包含 @ConfigurationProperties Bean。

@JdbcTest 启用的自动配置列表见附录。

默认情况下,JDBC 测试是事务性的,会在每次测试结束时回滚。详情请参见 Spring Framework 参考文档中的相关章节。如果这不是你想要的,你可以禁用某个测试或整个类的事务管理,具体做法如下:

import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;@JdbcTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
class MyTransactionalTests {}

如果您希望您的测试针对真实数据库运行,您可以使用 @AutoConfigureTestDatabase 注解,方法与 @DataJpaTest 相同。(请参阅 “自动配置的Data JPA 测试”)。

自动配置Data JDBC 测试

@DataJdbcTest@JdbcTest 类似,但用于使用 Spring Data JDBC 资源库的测试。默认情况下,它会配置一个内存嵌入式数据库、一个 JdbcTemplate 和 Spring Data JDBC 资源库。使用 @DataJdbcTest 注解时,只会扫描 AbstractJdbcConfiguration 子类,而不会扫描常规的 @Component@ConfigurationProperties Bean。@EnableConfigurationProperties 可用于包含 @ConfigurationProperties Bean。

附录中列出了 @DataJdbcTest 启用的自动配置。

默认情况下,Data JDBC 测试是事务性的,并在每次测试结束时回滚。有关详细信息,请参阅 Spring Framework 参考文档中的相关章节。如果这不是你想要的,你可以禁用某个测试或整个测试类的事务管理,如 JDBC 示例所示。
如果您希望您的测试针对真实数据库运行,您可以使用 @AutoConfigureTestDatabase 注解,方法与 @DataJpaTest 相同。(请参阅 “自动配置Data JPA 测试”)。

自动配置Data R2DBC 测试

@DataR2dbcTest@DataJdbcTest 类似,但用于使用 Spring Data R2DBC 资源库的测试。默认情况下,它会配置一个内存嵌入式数据库、一个 R2dbcEntityTemplate 和 Spring Data R2DBC 资源库。使用 @DataR2dbcTest 注解时,不会扫描常规 @Component@ConfigurationProperties Bean。@EnableConfigurationProperties 可用于包含 @ConfigurationProperties Bean。

@DataR2dbcTest 启用的自动配置列表见附录。

默认情况下,Data R2DBC 测试不是事务性的。
如果您希望测试在真实数据库中运行,可以使用 @AutoConfigureTestDatabase 注解,其使用方法与 @DataJpaTest 相同。(请参阅 “自动配置Data JPA 测试”)。

自动配置 jOOQ 测试

使用 @JooqTest 的方式与 @JdbcTest 类似,但用于与 jOOQ 相关的测试。由于 jOOQ 在很大程度上依赖于与数据库模式相对应的基于 Java 的模式,因此会使用现有的 DataSource。如果你想用内存数据库代替它,可以使用 @AutoConfigureTestDatabase 来覆盖这些设置。(使用 @JooqTest 注解时,不会扫描常规的 @Component@ConfigurationProperties Bean。@EnableConfigurationProperties 可用于包含 @ConfigurationProperties Bean。

@JooqTest 启用的自动配置列表见附录。

@JooqTest 配置 DSLContext。下面的示例展示了 @JooqTest 注解的使用:

import org.jooq.DSLContext;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jooq.JooqTest;@JooqTest
class MyJooqTests {@Autowiredprivate DSLContext dslContext;// ...}

JOOQ 测试是事务性的,默认情况下会在每个测试结束时回滚。如果这不是你想要的,你可以禁用某个测试或整个测试类的事务管理,如 JDBC 示例所示。

自动配置Data MongoDB 测试

您可以使用 @DataMongoTest 测试 MongoDB 应用程序。默认情况下,它会配置 MongoTemplate、扫描 @Document 类并配置 Spring Data MongoDB 存储库。使用 @DataMongoTest 注解时,不会扫描常规的 @Component@ConfigurationProperties Bean。@EnableConfigurationProperties 可用于包含 @ConfigurationProperties Bean。(有关在 Spring Boot 中使用 MongoDB 的更多信息,请参阅 “data.html”)。

@DataMongoTest 启用的自动配置设置列表见附录。

下面的类显示了 @DataMongoTest 注解的使用情况:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
import org.springframework.data.mongodb.core.MongoTemplate;@DataMongoTest
class MyDataMongoDbTests {@Autowiredprivate MongoTemplate mongoTemplate;// ...}

自动配置Data Neo4j 测试

你可以使用 @DataNeo4jTest 测试 Neo4j 应用程序。默认情况下,它会扫描 @Node 类,并配置 Spring Data Neo4j 资源库。使用 @DataNeo4jTest 注解时,不会扫描常规的 @Component@ConfigurationProperties Bean。@EnableConfigurationProperties 可用于包含 @ConfigurationProperties Bean。(有关在 Spring Boot 中使用 Neo4J 的更多信息,请参阅 “data.html”)。

@DataNeo4jTest 启用的自动配置设置列表见附录。

下面的示例展示了在 Spring Boot 中使用 Neo4J 测试的典型设置:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.neo4j.DataNeo4jTest;@DataNeo4jTest
class MyDataNeo4jTests {@Autowiredprivate SomeRepository repository;// ...}

默认情况下,Data Neo4j 测试是事务性的,并在每次测试结束时回滚。更多详情,请参阅 Spring Framework 参考文档中的相关章节。如果这不是你想要的,你可以禁用某个测试或整个类的事务管理,如下所示:

import org.springframework.boot.test.autoconfigure.data.neo4j.DataNeo4jTest;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;@DataNeo4jTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
class MyDataNeo4jTests {}

反应式访问不支持事务测试。如果使用这种风格,则必须如上所述配置 @DataNeo4jTest 测试。

自动配置Data Redis 测试

你可以使用 @DataRedisTest 测试 Redis 应用程序。默认情况下,它会扫描 @RedisHash 类并配置 Spring Data Redis 存储库。使用 @DataRedisTest 注解时,不会扫描常规的 @Component@ConfigurationProperties Bean。@EnableConfigurationProperties 可用于包含 @ConfigurationProperties Bean。(有关在 Spring Boot 中使用 Redis 的更多信息,请参阅 “data.html”)。

@DataRedisTest 启用的自动配置设置列表见附录。

下面的示例展示了 @DataRedisTest 注解的使用:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.redis.DataRedisTest;@DataRedisTest
class MyDataRedisTests {@Autowiredprivate SomeRepository repository;// ...}

自动配置Data LDAP 测试

您可以使用 @DataLdapTest 测试 LDAP 应用程序。默认情况下,它会配置内存中的嵌入式 LDAP(如果可用)、配置 LdapTemplate、扫描 @Entry 类并配置 Spring Data LDAP 资源库。使用 @DataLdapTest 注解时,不会扫描常规 @Component@ConfigurationProperties Bean。@EnableConfigurationProperties 可用于包含 @ConfigurationProperties Bean。(有关在 Spring Boot 中使用 LDAP 的更多信息,请参阅 “data.html”)。

@DataLdapTest 启用的自动配置设置列表见附录。

下面的示例展示了 @DataLdapTest 注解的使用:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.ldap.DataLdapTest;
import org.springframework.ldap.core.LdapTemplate;@DataLdapTest
class MyDataLdapTests {@Autowiredprivate LdapTemplate ldapTemplate;// ...}

内存中的嵌入式 LDAP 通常对测试非常有效,因为它速度快,而且不需要安装任何开发人员。但是,如果您更喜欢针对真实 LDAP 服务器运行测试,则应排除嵌入式 LDAP 自动配置,如下例所示:

import org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration;
import org.springframework.boot.test.autoconfigure.data.ldap.DataLdapTest;@DataLdapTest(excludeAutoConfiguration = EmbeddedLdapAutoConfiguration.class)
class MyDataLdapTests {// ...}

自动配置 REST 客户端

您可以使用 @RestClientTest 注解来测试 REST 客户端。默认情况下,它会自动配置对 Jackson、GSON 和 Jsonb 的支持,配置 RestTemplateBuilderRestClient.Builder,并添加对 MockRestServiceServer 的支持。当使用 @RestClientTest 注解时,常规的 @Component@ConfigurationProperties Bean 不会被扫描。@EnableConfigurationProperties 可用于包含 @ConfigurationProperties Bean。

@RestClientTest 启用的自动配置设置列表见附录。

应使用 @RestClientTestvaluecomponents 属性指定要测试的特定 Bean。
如果在被测 Bean 中使用 RestTemplateBuilder,并且在构建 RestTemplate 时调用了 RestTemplateBuilder.rootUri(String rootUri),则应在 MockRestServiceServer 期望中省略根 URI,如下例所示:

import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.client.RestClientTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.client.MockRestServiceServer;import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;@RestClientTest(RemoteVehicleDetailsService.class)
class MyRestTemplateServiceTests {@Autowiredprivate RemoteVehicleDetailsService service;@Autowiredprivate MockRestServiceServer server;@Testvoid getVehicleDetailsWhenResultIsSuccessShouldReturnDetails() {this.server.expect(requestTo("/greet/details")).andRespond(withSuccess("hello", MediaType.TEXT_PLAIN));String greeting = this.service.callRestService();assertThat(greeting).isEqualTo("hello");}}

在被测 Bean 中使用 RestClient.Builder 时,或使用 RestTemplateBuilder 而不调用 rootUri(String rootURI)时,必须在 MockRestServiceServer 期望中使用完整的 URI,如下例所示:

import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.client.RestClientTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.client.MockRestServiceServer;import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;@RestClientTest(RemoteVehicleDetailsService.class)
class MyRestClientServiceTests {@Autowiredprivate RemoteVehicleDetailsService service;@Autowiredprivate MockRestServiceServer server;@Testvoid getVehicleDetailsWhenResultIsSuccessShouldReturnDetails() {this.server.expect(requestTo("https://example.com/greet/details")).andRespond(withSuccess("hello", MediaType.TEXT_PLAIN));String greeting = this.service.callRestService();assertThat(greeting).isEqualTo("hello");}}

自动配置 Spring REST Docs 测试

您可以使用 @AutoConfigureRestDocs 注解,在使用 Mock MVC、REST Assured 或 WebTestClient 的测试中使用 Spring REST Docs。它消除了对 Spring REST Docs中 JUnit 扩展的需求。
@AutoConfigureRestDocs 可用于覆盖默认输出目录(如果使用 Maven,则为 target/generated-snippets;如果使用 Gradle,则为 build/generated-snippets)。它还可用于配置出现在任何文档 URI 中的主机、方案和端口。

使用 Mock MVC 自动配置 Spring REST Docs测试

@AutoConfigureRestDocs 可自定义 MockMvc Bean,以便在测试基于 servlet 的 Web 应用程序时使用 Spring REST Docs。您可以使用 @Autowired 注入它,并在测试中使用它,就像通常使用 Mock MVC 和 Spring REST Docs 时一样,如下例所示:

import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;@WebMvcTest(UserController.class)
@AutoConfigureRestDocs
class MyUserDocumentationTests {@Autowiredprivate MockMvc mvc;@Testvoid listUsers() throws Exception {this.mvc.perform(get("/users").accept(MediaType.TEXT_PLAIN)).andExpect(status().isOk()).andDo(document("list-users"));}}

如果您需要对 Spring REST 文档配置进行比 @AutoConfigureRestDocs 属性更多的控制,可以使用 RestDocsMockMvcConfigurationCustomizer Bean,如下例所示:

import org.springframework.boot.test.autoconfigure.restdocs.RestDocsMockMvcConfigurationCustomizer;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentationConfigurer;
import org.springframework.restdocs.templates.TemplateFormats;@TestConfiguration(proxyBeanMethods = false)
public class MyRestDocsConfiguration implements RestDocsMockMvcConfigurationCustomizer {@Overridepublic void customize(MockMvcRestDocumentationConfigurer configurer) {configurer.snippets().withTemplateFormat(TemplateFormats.markdown());}}

如果您想利用 Spring REST Docs对参数化输出目录的支持,可以创建一个 RestDocumentationResultHandler Bean。自动配置会调用此结果处理程序的 alwaysDo,从而使每次 MockMvc 调用都自动生成默认片段。下面的示例显示了一个 RestDocumentationResultHandler 的定义:

import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation;
import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler;@TestConfiguration(proxyBeanMethods = false)
public class MyResultHandlerConfiguration {@Beanpublic RestDocumentationResultHandler restDocumentation() {return MockMvcRestDocumentation.document("{method-name}");}}
使用 WebTestClient 自动配置 Spring REST Docs测试

在测试反应式 Web 应用程序时,@AutoConfigureRestDocs 还可以与 WebTestClient 一起使用。您可以使用 @Autowired 注入它,并在测试中使用它,就像通常使用 @WebFluxTest 和 Spring REST Docs一样,如下例所示:

import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs;
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
import org.springframework.test.web.reactive.server.WebTestClient;import static org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation.document;@WebFluxTest
@AutoConfigureRestDocs
class MyUsersDocumentationTests {@Autowiredprivate WebTestClient webTestClient;@Testvoid listUsers() {this.webTestClient.get().uri("/").exchange().expectStatus().isOk().expectBody().consumeWith(document("list-users"));}}

如果您需要对 Spring REST Docs配置进行比 @AutoConfigureRestDocs 属性更多的控制,可以使用 RestDocsWebTestClientConfigurationCustomizer Bean,如下例所示:

import org.springframework.boot.test.autoconfigure.restdocs.RestDocsWebTestClientConfigurationCustomizer;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.restdocs.webtestclient.WebTestClientRestDocumentationConfigurer;@TestConfiguration(proxyBeanMethods = false)
public class MyRestDocsConfiguration implements RestDocsWebTestClientConfigurationCustomizer {@Overridepublic void customize(WebTestClientRestDocumentationConfigurer configurer) {configurer.snippets().withEncoding("UTF-8");}}

如果想利用 Spring REST Docs 对参数化输出目录的支持,可以使用 WebTestClientBuilderCustomizer 为每个实体交换结果配置一个消费者。下面的示例展示了这样一个 WebTestClientBuilderCustomizer 的定义:

import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.test.web.reactive.server.WebTestClientBuilderCustomizer;
import org.springframework.context.annotation.Bean;import static org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation.document;@TestConfiguration(proxyBeanMethods = false)
public class MyWebTestClientBuilderCustomizerConfiguration {@Beanpublic WebTestClientBuilderCustomizer restDocumentation() {return (builder) -> builder.entityExchangeResultConsumer(document("{method-name}"));}}
使用 REST Assured 自动配置 Spring REST Docs测试

@AutoConfigureRestDocs 使预设为使用 Spring REST Docs的 RequestSpecification Bean 可供测试使用。您可以使用 @Autowired 注入该 Bean,并在测试中使用它,就像通常使用 REST Assured 和 Spring REST Docs 时那样,如下例所示:

import io.restassured.specification.RequestSpecification;
import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.server.LocalServerPort;import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.is;
import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.document;@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureRestDocs
class MyUserDocumentationTests {@Testvoid listUsers(@Autowired RequestSpecification documentationSpec, @LocalServerPort int port) {given(documentationSpec).filter(document("list-users")).when().port(port).get("/").then().assertThat().statusCode(is(200));}}

如果您需要对 Spring REST 文档配置进行比 @AutoConfigureRestDocs 属性更多的控制,则可以使用 RestDocsRestAssuredConfigurationCustomizer Bean,如下例所示:

import org.springframework.boot.test.autoconfigure.restdocs.RestDocsRestAssuredConfigurationCustomizer;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.restdocs.restassured.RestAssuredRestDocumentationConfigurer;
import org.springframework.restdocs.templates.TemplateFormats;@TestConfiguration(proxyBeanMethods = false)
public class MyRestDocsConfiguration implements RestDocsRestAssuredConfigurationCustomizer {@Overridepublic void customize(RestAssuredRestDocumentationConfigurer configurer) {configurer.snippets().withTemplateFormat(TemplateFormats.markdown());}}

自动配置 Spring Web 服务测试

自动配置 Spring Web 服务客户端测试

您可以使用 @WebServiceClientTest 测试使用 Spring Web 服务项目调用 Web 服务的应用程序。默认情况下,它会配置一个模拟 WebServiceServer Bean,并自动自定义 WebServiceTemplateBuilder。(有关使用 Spring Boot 的 Web 服务的更多信息,请参阅 “io.html”)。

@WebServiceClientTest 启用的自动配置设置列表见附录。

下面的示例展示了 @WebServiceClientTest 注解的使用:

import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.webservices.client.WebServiceClientTest;
import org.springframework.ws.test.client.MockWebServiceServer;
import org.springframework.xml.transform.StringSource;import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.ws.test.client.RequestMatchers.payload;
import static org.springframework.ws.test.client.ResponseCreators.withPayload;@WebServiceClientTest(SomeWebService.class)
class MyWebServiceClientTests {@Autowiredprivate MockWebServiceServer server;@Autowiredprivate SomeWebService someWebService;@Testvoid mockServerCall() {this.server.expect(payload(new StringSource("<request/>"))).andRespond(withPayload(new StringSource("<response><status>200</status></response>")));assertThat(this.someWebService.test()).extracting(Response::getStatus).isEqualTo(200);}}
自动配置 Spring Web 服务服务器测试

您可以使用 @WebServiceServerTest 测试使用 Spring Web 服务项目实现 Web 服务的应用程序。默认情况下,它会配置一个 MockWebServiceClient Bean,用于调用 Web 服务端点。(有关在 Spring Boot 中使用 Web 服务的更多信息,请参阅 “io.html”)。

@WebServiceServerTest 启用的自动配置设置列表见附录。

下面的示例展示了 @WebServiceServerTest 注解的使用:

import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.webservices.server.WebServiceServerTest;
import org.springframework.ws.test.server.MockWebServiceClient;
import org.springframework.ws.test.server.RequestCreators;
import org.springframework.ws.test.server.ResponseMatchers;
import org.springframework.xml.transform.StringSource;@WebServiceServerTest(ExampleEndpoint.class)
class MyWebServiceServerTests {@Autowiredprivate MockWebServiceClient client;@Testvoid mockServerCall() {this.client.sendRequest(RequestCreators.withPayload(new StringSource("<ExampleRequest/>"))).andExpect(ResponseMatchers.payload(new StringSource("<ExampleResponse>42</ExampleResponse>")));}}

额外的自动配置和切片功能

每个片段都提供一个或多个 @AutoConfigure... 注解,即定义应作为片段一部分的自动配置。可通过创建自定义 @AutoConfigure... 注解或在测试中添加 @ImportAutoConfiguration 来逐个测试添加其他自动配置,如下例所示:

import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration;
import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest;@JdbcTest
@ImportAutoConfiguration(IntegrationAutoConfiguration.class)
class MyJdbcTests {}

请确保不要使用常规的 @Import 注解来导入自动配置,因为 Spring Boot 会以特定的方式处理它们。

另外,还可以为切片注释的任何用途添加额外的自动配置,方法是在 META-INF/spring 中存储的文件中注册这些配置,如下例所示:
META-INF/spring/org.springframework.boot.test.autoconfigure.jdbc.JdbcTest.imports

com.example.IntegrationAutoConfiguration

在此示例中,com.example.IntegrationAutoConfiguration 会在每个使用 @JdbcTest 注释的测试中启用。

您可以在此文件中使用带有 # 的注释。

只要使用 @ImportAutoConfiguration 对片段或 @AutoConfigure... 注释进行元注解,就可以通过这种方式对其进行自定义。

用户配置和切片

如果你的代码结构合理,你的 @SpringBootApplication 类就会被默认用作测试的配置。
因此,重要的是不要在应用程序的主类中添加针对其特定功能区域的配置设置。
假设您使用的是 Spring Data MongoDB,您依赖于它的自动配置,并启用了审计功能。你可以将 @SpringBootApplication 定义如下:

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.mongodb.config.EnableMongoAuditing;@SpringBootApplication
@EnableMongoAuditing
public class MyApplication {// ...}

由于该类是测试的源配置,因此任何片段测试实际上都会尝试启用 Mongo 审计,这绝对不是你想要做的。推荐的方法是将特定区域的配置转移到与应用程序同级的单独 @Configuration 类中,如下例所示:

import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.config.EnableMongoAuditing;@Configuration(proxyBeanMethods = false)
@EnableMongoAuditing
public class MyMongoConfiguration {// ...}

根据应用程序的复杂程度,您可以为自定义设置设置一个 @Configuration 类,或者为每个域区设置一个类。后一种方法允许您在必要时使用 @Import 注解在其中一个测试中启用它。有关何时需要为切片测试启用特定 @Configuration 类的更多详情,请参阅本节。

测试片从扫描中排除 @Configuration 类。例如,在 @WebMvcTest 中,以下配置不会在测试片段加载的应用程序上下文中包含给定的 WebMvcConfigurer Bean:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration(proxyBeanMethods = false)
public class MyWebConfiguration {@Beanpublic WebMvcConfigurer testConfigurer() {return new WebMvcConfigurer() {// ...};}}

不过,下面的配置会导致测试片加载自定义 WebMvcConfigurer

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Component
public class MyWebMvcConfigurer implements WebMvcConfigurer {// ...}

另一个造成混乱的原因是类路径扫描。假设您以合理的方式编排代码,但需要扫描一个额外的软件包。您的应用程序可能类似于以下代码:

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;@SpringBootApplication
@ComponentScan({ "com.example.app", "com.example.another" })
public class MyApplication {// ...}

这样做会有效地覆盖默认组件扫描指令,并产生扫描这两个包的副作用,而与您选择的片段无关。例如,@DataJpaTest 似乎会突然扫描应用程序的组件和用户配置。同样,将自定义指令移至单独的类是解决这一问题的好方法。

如果你不能这样做,可以在测试的层次结构中创建一个 @SpringBootConfiguration 来代替它。或者,你也可以为测试指定一个源,从而禁用查找默认源的行为。

使用 Spock 测试 Spring Boot 应用程序

Spock 2.2 或更高版本可用于测试 Spring Boot 应用程序。为此,请在应用程序的构建中添加对 -groovy-4.0 版本 Spock 的 spock-spring 模块的依赖关系。spock-spring 将 Spring 的测试框架集成到 Spock 中。更多详情,请参阅 Spock 的 Spring 模块文档。

测试容器

Testcontainers 库提供了一种管理在 Docker 容器内运行的服务的方法。它与 JUnit 集成,让您可以编写一个测试类,在任何测试运行之前启动容器。Testcontainers 对于编写与真实后端服务(如 MySQL、MongoDB、Cassandra 等)对话的集成测试特别有用。
Testcontainers 在 Spring Boot 测试中的使用方法如下:

import org.junit.jupiter.api.Test;
import org.testcontainers.containers.Neo4jContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;import org.springframework.boot.test.context.SpringBootTest;@Testcontainers
@SpringBootTest
class MyIntegrationTests {@Containerstatic Neo4jContainer<?> neo4j = new Neo4jContainer<>("neo4j:5");@Testvoid myTest() {// ...}}

这将在运行任何测试之前启动一个运行 Neo4j 的 docker 容器(如果本地运行 Docker)。在大多数情况下,您需要配置应用程序以连接到容器中运行的服务。

连接服务

服务连接是与任何远程服务的连接。Spring Boot 的自动配置可以获取服务连接的详细信息,并利用它们建立与远程服务的连接。这样做时,连接详细信息优先于任何与连接相关的配置属性。
使用 Testcontainers 时,通过在测试类中注释容器字段,可以为在容器中运行的服务自动创建连接详细信息。

import org.junit.jupiter.api.Test;
import org.testcontainers.containers.Neo4jContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;@Testcontainers
@SpringBootTest
class MyIntegrationTests {@Container@ServiceConnectionstatic Neo4jContainer<?> neo4j = new Neo4jContainer<>("neo4j:5");@Testvoid myTest() {// ...}}

通过 @ServiceConnection,上述配置允许应用程序中与 Neo4j 相关的 Bean 与运行在 Testcontainers 管理的 Docker 容器中的 Neo4j 通信。这是通过自动定义 Neo4jConnectionDetails Bean 来实现的,Neo4j 自动配置会使用该 Bean,并覆盖任何与连接相关的配置属性。

您需要将 spring-boot-testcontainers 模块添加为测试依赖项,以便使用 Testcontainers 服务连接。

服务连接注解由在 spring.factories 中注册的 ContainerConnectionDetailsFactory 类处理。ContainerConnectionDetailsFactory 可根据特定容器子类或 Docker 映像名称创建 ConnectionDetails Bean。
spring-boot-testcontainers jar 中提供了以下服务连接工厂:

Connection DetailsMatched on
ActiveMQConnectionDetails名为 "symptoma/activemq "的容器
CassandraConnectionDetailsCassandraContainer类型的容器
CouchbaseConnectionDetailsCouchbaseContainer类型的容器
ElasticsearchConnectionDetailsElasticsearchContainer类型的容器
FlywayConnectionDetailsJdbcDatabaseContainer类型的容器
JdbcConnectionDetailsJdbcDatabaseContainer类型的容器
KafkaConnectionDetailsKafkaContainerRedpandaContainer类型的容器
LiquibaseConnectionDetailsJdbcDatabaseContainer类型的容器
MongoConnectionDetailsMongoDBContainer类型的容器
Neo4jConnectionDetailsNeo4jContainer类型的容器
OtlpMetricsConnectionDetails名为 “otel/opentelemetry-collector-contrib” 的容器
OtlpTracingConnectionDetails名为 “otel/opentelemetry-collector-contrib” 的容器
PulsarConnectionDetailsPulsarContainer类型的容器
R2dbcConnectionDetails类型为 MariaDBContainerMSSQLServerContainerMySQLContainerOracleContainerPostgreSQLContainer 的容器
RabbitConnectionDetailsRabbitMQContainer类型的容器
RedisConnectionDetails名为 "redis "的容器
ZipkinConnectionDetails名为 "openzipkin/zipkin "的容器

默认情况下,将为给定容器创建所有适用的连接详情 Bean。例如,PostgreSQLContainer 将同时创建 JdbcConnectionDetailsR2dbcConnectionDetails
如果只想创建适用类型的子集,可以使用 @ServiceConnection 的 type 属性。

默认情况下,Container.getDockerImageName() 用于获取用于查找连接详细信息的名称。只要 Spring Boot 能够获取 Container 的实例(如上例中使用静态字段的情况),该方法就能正常工作。
如果使用 @Bean 方法,Spring Boot 不会调用 bean 方法来获取 Docker 映像名称,因为这会导致急于初始化的问题。相反,Bean 方法的返回类型会被用来查找应使用的连接细节。只要您使用的是类型化容器,例如 Neo4jContainerRabbitMQContainer,这种方法就会起作用。如果您使用的是 GenericContainer,例如 Redis,则此方法将停止工作,如下例所示:

import org.testcontainers.containers.GenericContainer;import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.context.annotation.Bean;@TestConfiguration(proxyBeanMethods = false)
public class MyRedisConfiguration {@Bean@ServiceConnection(name = "redis")public GenericContainer<?> redisContainer() {return new GenericContainer<>("redis:7");}}

Spring Boot 无法从 GenericContainer 中得知使用了哪个容器映像,因此必须使用 @ServiceConnectionname 属性来提供该提示。
您也可以使用 @ServiceConnectionname 属性来覆盖将使用的连接细节,例如在使用自定义映像时。如果你使用的是 Docker 映像 registry.mycompany.com/mirror/myredis,你可以使用 @ServiceConnection(name="redis") 来确保创建 RedisConnectionDetails

动态属性

@DynamicPropertySource 是服务连接的一个略显冗长但也更灵活的替代方法。静态 @DynamicPropertySource 方法允许向 Spring Environment 添加动态属性值。

import org.junit.jupiter.api.Test;
import org.testcontainers.containers.Neo4jContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;@Testcontainers
@SpringBootTest
class MyIntegrationTests {@Containerstatic Neo4jContainer<?> neo4j = new Neo4jContainer<>("neo4j:5");@Testvoid myTest() {// ...}@DynamicPropertySourcestatic void neo4jProperties(DynamicPropertyRegistry registry) {registry.add("spring.neo4j.uri", neo4j::getBoltUrl);}}

上述配置允许应用程序中与 Neo4j 相关的 Bean 与运行在 Testcontainers 管理的 Docker 容器中的 Neo4j 通信。

测试工具

Spring-boot 中打包了一些测试实用类,它们在测试应用程序时非常有用。

ConfigDataApplicationContextInitializer

ConfigDataApplicationContextInitializer 是一个 ApplicationContextInitializer,你可以将它应用于你的测试,以加载 Spring Boot application.properties 文件。当你不需要 @SpringBootTest 提供的全套功能时,可以使用它,如下例所示:

import org.springframework.boot.test.context.ConfigDataApplicationContextInitializer;
import org.springframework.test.context.ContextConfiguration;@ContextConfiguration(classes = Config.class, initializers = ConfigDataApplicationContextInitializer.class)
class MyConfigFileTests {// ...}

仅使用 ConfigDataApplicationContextInitializer 并不支持 @Value("${...}") 注入。它的唯一作用是确保将 application.properties 文件加载到 Spring 的环境中。要获得 @Value 支持,需要额外配置 PropertySourcesPlaceholderConfigurer 或使用 @SpringBootTest 自动配置。

TestPropertyValues

TestPropertyValues 可让您快速向 ConfigurableEnvironmentConfigurableApplicationContext 添加属性。您可以使用 key=value 字符串调用它,如下所示:

import org.junit.jupiter.api.Test;import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.mock.env.MockEnvironment;import static org.assertj.core.api.Assertions.assertThat;class MyEnvironmentTests {@Testvoid testPropertySources() {MockEnvironment environment = new MockEnvironment();TestPropertyValues.of("org=Spring", "name=Boot").applyTo(environment);assertThat(environment.getProperty("name")).isEqualTo("Boot");}}

OutputCapture

OutputCapture 是一个 JUnit 扩展,可用于捕获 System.outSystem.err 输出。要使用它,请添加 @ExtendWith(OutputCaptureExtension.class) 并将 CapturedOutput 作为参数注入测试类构造函数或测试方法,如下所示:

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;import org.springframework.boot.test.system.CapturedOutput;
import org.springframework.boot.test.system.OutputCaptureExtension;import static org.assertj.core.api.Assertions.assertThat;@ExtendWith(OutputCaptureExtension.class)
class MyOutputCaptureTests {@Testvoid testName(CapturedOutput output) {System.out.println("Hello World!");assertThat(output).contains("World");}}

TestRestTemplate

TestRestTemplate 是 Spring RestTemplate 的便捷替代品,在集成测试中非常有用。你可以获得一个普通模板或一个发送 Basic HTTP 身份验证(带用户名和密码)的模板。无论哪种情况,模板都是容错的。这意味着它不会在出现 4xx 和 5xx 错误时抛出异常,从而以测试友好的方式运行。相反,可以通过返回的 ResponseEntity 及其状态代码检测到此类错误。

TestRestTemplate 是 Spring RestTemplate 的便捷替代品,在集成测试中非常有用。你可以获得一个普通模板或一个发送 Basic HTTP 身份验证(带用户名和密码)的模板。无论哪种情况,模板都是容错的。这意味着它不会在出现 4xx 和 5xx 错误时抛出异常,从而以测试友好的方式运行。相反,可以通过返回的 ResponseEntity 及其状态代码检测到此类错误。

建议使用 Apache HTTP 客户端(5.1 或更高版本),但并非必须。如果您的类路径上有 Apache HTTP 客户端,TestRestTemplate 会对客户端进行适当配置。如果使用的是 Apache HTTP 客户端,则会启用一些额外的测试友好功能:

  • 不跟踪重定向(因此可以断言响应位置)。
  • 忽略 Cookie(因此模板是无状态的)。

TestRestTemplate 可直接在集成测试中实例化,如下例所示:

import org.junit.jupiter.api.Test;import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.ResponseEntity;import static org.assertj.core.api.Assertions.assertThat;class MyTests {private final TestRestTemplate template = new TestRestTemplate();@Testvoid testRequest() {ResponseEntity<String> headers = this.template.getForEntity("https://myhost.example.com/example", String.class);assertThat(headers.getHeaders().getLocation()).hasHost("other.example.com");}}

另外,如果使用带有 WebEnvironment.RANDOM_PORTWebEnvironment.DEFINED_PORT@SpringBootTest 注解,就可以注入一个完全配置好的 TestRestTemplate 并开始使用。如有必要,还可通过 RestTemplateBuilder Bean 进行其他自定义。任何未指定主机和端口的 URL 都会自动连接到嵌入式服务器,如下例所示:

import java.time.Duration;import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpHeaders;import static org.assertj.core.api.Assertions.assertThat;@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class MySpringBootTests {@Autowiredprivate TestRestTemplate template;@Testvoid testRequest() {HttpHeaders headers = this.template.getForEntity("/example", String.class).getHeaders();assertThat(headers.getLocation()).hasHost("other.example.com");}@TestConfiguration(proxyBeanMethods = false)static class RestTemplateBuilderConfiguration {@BeanRestTemplateBuilder restTemplateBuilder() {return new RestTemplateBuilder().setConnectTimeout(Duration.ofSeconds(1)).setReadTimeout(Duration.ofSeconds(1));}}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/232909.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ChatGPT引领AI时代:程序员、项目经理、产品经理、架构师、Python量化交易师的翅膀

&#x1f482; 个人网站:【 海拥】【神级代码资源网站】【办公神器】&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交流的小伙伴&#xff0c;请点击【全栈技术交流群】 在当今AI时代&#xff0c;ChatGPT作为一项卓越…

信号驱动IO(新)

信号驱动IO是与内核建立SIGIO的信号处理函数并设置回调&#xff0c;当内核有FD就绪时&#xff0c;内核会发出SIGIO信号通知用户进程&#xff0c;在这期间用户应用进程可以执行其他业务&#xff0c;无需阻塞等待。 这个信号驱动IO多好啊&#xff0c;直接替代IO多路复用不好吗&am…

数字化医疗新篇章:构建智能医保支付购药系统

在迎接数字化医疗时代的挑战和机遇中&#xff0c;智能医保支付购药系统的建设显得尤为重要。本文将深入介绍如何通过先进的技术实现&#xff0c;构建一套智能、高效的医保支付购药系统&#xff0c;为全面建设健康中国贡献力量。 1. 引言 随着医疗科技的飞速发展&#xff0c;…

log4j日志打印配置

文件名&#xff1a;log4j2.xml <?xml version"1.0" encoding"UTF-8"?> <configuration monitorInterval"5"><!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL --&…

Radzen Blazor 分享

Blazor 是个好东西&#xff0c;可惜在我们这种大环境下&#xff0c;用的人还是少&#xff0c;但是我们不能抵挡先进的生产力&#xff0c;特别是如果您是C#爱好者&#xff0c;更需要不要错过使用这个利器&#xff0c;起码个人开发个基本应用真是快的不得了。 本节只做一个简单的…

echarts饼图扇形之间设置间距

查看文档以及网上查找&#xff0c;都是将边框颜色设置成和背景色一样&#xff0c;但是当背景是图片的时候就不适用了&#xff0c;试了很多方式都不理想&#xff0c;没办法只能从数据上下手了&#xff0c;最终效果如下图&#xff0c; 思路&#xff1a;将list中的数据每一条后面插…

理解BeEF的架构

BeEF的组件和工作原理BeEF&#xff08;The Browser Exploitation Framework&#xff09;是一款用于浏览器渗透测试和漏洞利用的强大工具。它由多个组件组成&#xff0c;这些组件协同工作以实现对受害者浏览器的控制和攻击。本文将深入探讨BeEF的各个组件和其工作原理&#xff0…

区域和检索算法(leetcode第303题)

题目描述&#xff1a; 给定一个整数数组 nums&#xff0c;处理以下类型的多个查询:计算索引 left 和 right &#xff08;包含 left 和 right&#xff09;之间的 nums 元素的 和 &#xff0c;其中 left < right 实现 NumArray 类&#xff1a;NumArray(int[] nums) 使用数组…

AndroidStudio使用配置详解

见&#xff1a;GitHub - eHackyd/AndroidStudio: AndroidStudio的各种使用配置说明

将mavros仓库上传到gitee,用于二次开发

以mavros为例&#xff08;mavlink同理&#xff09; 按照官网repo提供的安装方法&#xff08;参考&#xff1a;mavros源码安装与配置&#xff09;&#xff0c;将mavros相关的软件包下载到本地&#xff0c;考虑到后面要进行二次开发&#xff0c;所以打算在gitee上做一个备份。同时…

干货教学!!!RHEL8中ansible中常用模块的使用

内容很长各位大老爷耐心观看 本章主要介绍ansible中最常见模块的使用 文件管理模块软件包管理模块服务管理模块磁盘管理模块用户管理模块防火墙管理模块 ansible的基本用法如下 ansible 机器名 -m 模块x -a “模块的参数” 对被管理机器执行不同的操作&#xff0c;只需要调…

【深度学习】Sentence Embedding-BERT-Whitening

前言 flow模型本身很弱&#xff0c;BERT-flow里边使用的flow模型更弱&#xff0c;所以flow模型不大可能在BERT-flow中发挥至关重要的作用。反过来想&#xff0c;那就是也许我们可以找到更简单直接的方法达到BERT-flow的效果。 BERT-whitening则认为&#xff0c;flow模型中涉及到…

C语言第五十三弹----模拟使用strncmp函数

使用C语言模拟使用strncmp函数 trncmp 是一个 C 语言标准库函数&#xff0c;用于比较两个字符串的前 n 个字符是否相等。它的函数声明为&#xff1a; int strncmp(const char *str1, const char *str2, size_t n);其中&#xff0c;str1 和 str2 是要被比较的两个字符串&#…

AWS 知识一:如何在AWS上启动云AD服务器(详细到极致)

前言&#xff1a; 首先这里指的云AD服务器&#xff0c;只是为了让读友更好理解。云AD服务器在AWS中称为目录。AWS一共提供了4种目录类别&#xff0c;下面我将全程使用AWS托管微软AD这种目录类别进行示例。他完全提供了和Microsoft AD的功能&#xff0c;包括NTLM&#xff0c;Ker…

欧洲版OpenAI疑似将在24年发布并开源GPT-4级别模型!

大家好&#xff0c;我是二狗。 今天在推特上看到一条振奋人心的消息&#xff1a; “ 欧洲版OpenAI、法国初创公司 Mistral 首席执行官 Arthur Mensch 在法国国家广播电台宣布&#xff0c;Mistral 将在 2024 年发布开源 GPT-4 级别模型。” 这位老哥接着表示甚至可能是免费的&a…

传统软件集成AI大模型——Function Calling

传统软件和AI大模型的胶水——Function Calling 浅谈GPT对传统软件的影响Function Calling做了什么&#xff0c;为什么选择Function CallingFunction Calling简单例子&#xff0c;如何使用使用场景 浅谈GPT对传统软件的影响 目前为止好多人对chatGPT的使用才停留在OpenAI自己提…

数据可视化---箱线图

类别内容导航机器学习机器学习算法应用场景与评价指标机器学习算法—分类机器学习算法—回归机器学习算法—聚类机器学习算法—异常检测机器学习算法—时间序列数据可视化数据可视化—折线图数据可视化—箱线图数据可视化—柱状图数据可视化—饼图、环形图、雷达图统计学检验箱…

【MySQL】数据库和表的操作

数据库和表的操作 一、数据库的操作1. 创建数据库2. 字符集和校验规则&#xff08;1&#xff09;查看系统默认字符集以及校验规则&#xff08;2&#xff09;查看数据库支持的字符集&#xff08;3&#xff09;查看数据库支持的字符集校验规则&#xff08;4&#xff09;校验规则对…

RabbitMQ 基础

1.初识RabbitMQ 1.1.同步调用 我们现在基于OpenFeign的调用都属于是同步调用&#xff0c;那么这种方式存在哪些问题呢&#xff1f; 拓展性差性能下降级联失败 而要解决这些问题&#xff0c;我们就必须用异步调用的方式来代替同步调用。 1.2.异步调用 异步调用方式其实就是基…

EG网关网口连接MCGS触摸屏应用案例

EG网关网口连接MCGS触摸屏应用案例 前言&#xff1a;MCGS触摸屏广泛应于工业控制领域&#xff0c;是一款性能高&#xff0c;运行稳定的人机交互设备。此次我们要把MCGS的TPC7062系列触摸屏通过Modbus协议连接EG系列网关&#xff0c;将数据传输到EMCP物联网云平台&#xff0c;实…