欢迎访问shiker.tech

请允许在我们的网站上展示广告

您似乎使用了广告拦截器,请关闭广告拦截器。我们的网站依靠广告获取资金。

【译文】springboot核心功能-单元测试
(last modified Nov 28, 2023, 9:36 PM )
by
侧边栏壁纸
  • 累计撰写 192 篇文章
  • 累计创建 66 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

【译文】springboot核心功能-单元测试

橙序员
2022-08-20 / 0 评论 / 0 点赞 / 892 阅读 / 12 字 / 正在检测百度是否收录... 正在检测必应是否收录...
文章摘要(AI生成)

Spring Boot 提供了丰富的测试支持,包括spring-boot-test和spring-boot-test-autoconfigure两个模块。大多数开发者使用spring-boot-starter-test作为依赖,它导入了Spring Boot测试模块以及JUnit Jupiter、AssertJ、Hamcrest等库。
如果你有使用JUnit 4的测试,可以通过添加对junit-vintage-engine的依赖来使用JUnit 5的老式引擎来运行它们。需要注意的是,在添加junit-vintage-engine的依赖时,可能需要排除org.hamcrest:hamcrest-core依赖,因为它已经包含在spring-boot-starter-test中。
spring-boot-starter-testStarter在测试范围内提供了以下库的依赖:
- JUnit 5:用于编写单元测试的事实标准。
- Spring Test & Spring Boot Test:提供了Spring Boot应用程序的实用程序和集成测试支持。
- AssertJ:一个流畅的断言库,用于编写更具表达力的测试断言。
- Hamcrest:一个匹配器对象库,用于编写更具可读性和灵活性的断言。
- Mockito:用于编写测试时创建和操作模拟对象的库。
总结:Spring Boot提供了强大的测试支持,可以帮助开发人员编写单元测试和集成测试。使用spring-boot-starter-testStarter可以导入所需的测试库,同时还可以使用JUnit 5的老式引擎来运行JUnit 4的测试。

8. 单元测试

Spring Boot 提供了许多实用程序和注解来帮助测试您的应用程序。测试支持由两个模块提供:包含核心项目的spring-boot-test,并支持测试自动配置的spring-boot-test-autoconfigure

大多数开发人员使用spring-boot-starter-test“Starter”,它导入了 Spring Boot 测试模块以及 JUnit Jupiter、AssertJ、Hamcrest 和许多其他有用的库。

如果您有使用 JUnit 4 的测试,则可以使用 JUnit 5 的老式引擎来运行它们。要使用老式引擎,请添加对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>

org.hamcrest:hamcresthamcrest-core被排除在外,那是spring-boot-starter-test的一部分。

8.1. 测试范围依赖

spring-boot-starter-testStarter”(在test scope中)包含以下提供的库:

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

我们通常发现这些通用库在编写测试时很有用。如果这些库不适合您的需求,您可以添加自己的其他测试依赖项。

8.2. 测试 Spring 应用程序

依赖注入的主要优点之一是它应该使您的代码更容易进行单元测试。您可以使用new运算符来实例化对象,甚至无需涉及 Spring。您还可以使用模拟对象而不是真正的依赖项。

通常,您需要超越单元测试并开始集成测试(使用 Spring ApplicationContext)。能够执行集成测试而不需要部署您的应用程序或需要连接到其他基础设施是很有用的。

Spring 框架包括一个用于此类集成测试的专用测试模块。你可以直接声明一个org.springframework:spring-test依赖或者使用spring-boot-starter-test“Starter”来传递它。

如果您以前没有使用过该spring-test模块,则应首先阅读 Spring Framework 参考文档的相关部分

8.3. 测试 Spring Boot 应用程序

Spring Boot 应用程序是 Spring ApplicationContext,因此除了您通常使用普通 Spring 上下文执行的操作之外,无需进行任何特别的测试即可对其进行测试。

默认情况下,Spring Boot 的外部属性、日志记录和其他功能仅在您用于SpringApplication创建上下文时安装在上下文中。

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(默认):加载web ApplicationContext并提供模拟网络环境。使用此注解时不启动嵌入式服务器。如果您的类路径上没有可用的 Web 环境,则此模式会透明地回退到创建常规的 non-web ApplicationContext。它可以与您的 Web 应用程序结合使用@AutoConfigureMockMvc@AutoConfigureWebTestClient用于基于模拟的测试。
  • RANDOM_PORT: 加载WebServerApplicationContext并提供一个真实的网络环境。嵌入式服务器会启动并侦听随机端口。
  • DEFINED_PORT: 加载WebServerApplicationContext并提供一个真实的网络环境。嵌入式服务器会启动并侦听定义的端口(来自您的application.properties)或默认的8080端口.
  • NONE:通过使用SpringApplication加载一个ApplicationContext但不提供任何Web 环境(模拟或其他)。

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

如果您的应用程序为管理服务器使用不同的端口, 使用webEnvironment = WebEnvironment.RANDOM_PORT@SpringBootTest还将在单独的随机端口上启动管理服务器。

8.3.1. 检测 Web 应用程序类型

如果 Spring MVC 可用,则配置常规的基于 MVC 的应用程序上下文。如果您只有 Spring WebFlux,我们将检测到它并配置一个基于 WebFlux 的应用程序上下文。

如果两者都存在,则 Spring MVC 优先。如果要在这种情况下测试响应式 Web 应用程序,则必须设置spring.main.web-application-type属性:

@SpringBootTest(properties = "spring.main.web-application-type=reactive")
class MyWebFluxTests {

    // ...

}

8.3.2. 检测测试配置

如果您熟悉 Spring Test Framework,您可能习惯于使用@ContextConfiguration(classes=…)以指定要加载的 Spring @Configuration。或者,您可能经常在测试中使用嵌套@Configuration类。

在测试 Spring Boot 应用程序时,通常不需要这样做。只要您没有明确定义,Spring Boot 的@*Test注解就会自动搜索您的主要配置。

搜索算法从包含测试的包开始,直到找到一个用@SpringBootApplication@SpringBootConfiguration注解的类。只要您以合理的方式构建代码,通常会找到您的主要配置。

如果您使用测试注解来测试应用程序的更具体部分,则应避免在主方法的应用程序类上添加特定于特定区域的配置设置。@SpringBootApplication的底层组件扫描配置定义了用于确保切面按预期工作的排除过滤器。如果您在 @SpringBootApplication注解的类上使用显式@ComponentScan指令,请注意这些过滤器将被禁用。如果您使用切面,则应重新定义它们。

如果要自定义主要配置,可以使用嵌套@TestConfiguration类。与将使用嵌套@Configuration类代替应用程序的主要配置不同,嵌套@TestConfiguration类是在应用程序的主要配置之外使用的。

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

8.3.3. 排除测试配置

如果您的应用程序使用组件扫描(例如,如果您使用@SpringBootApplication@ComponentScan),您可能会发现仅为特定测试创建的顶级配置类意外地在各处被拾取。

正如我们之前看到的@TestConfiguration可以在测试的内部类上使用来自定义主要配置。当放置在顶级类上时,@TestConfiguration表示不应通过扫描获取src/test/java中的类。然后,您可以在需要的地方显式导入该类,如以下示例所示:

@SpringBootTest
@Import(MyTestsConfiguration.class)
class MyTests {

    @Test
    void exampleTest() {
        // ...
    }

}

如果您直接使用@ComponentScan(即不通过@SpringBootApplication),则需要向TypeExcludeFilter注册。有关详细信息,请参阅Javadoc

8.3.4. 使用应用程序参数

如果您的应用程序需要arguments,您可以使用@SpringBootTestargs属性注入它们。

@SpringBootTest(args = "--app.test=one")
class MyApplicationArgumentTests {

    @Test
    void applicationArgumentsPopulated(@Autowired ApplicationArguments args) {
        assertThat(args.getOptionNames()).containsOnly("app.test");
        assertThat(args.getOptionValues("app.test")).containsOnly("one");
    }

}

8.3.5. 使用模拟环境进行测试

默认情况下,@SpringBootTest不会启动服务器,而是设置一个模拟环境来测试 Web 端点。

使用 Spring MVC,我们可以使用MockMvc或者WebTestClient查询我们的 Web 端点,如下例所示:

@SpringBootTest
@AutoConfigureMockMvc
class MyMockMvcTests {

    @Test
    void 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
    @Test
    void testWithWebTestClient(@Autowired WebTestClient webClient) {
        webClient
                .get().uri("/")
                .exchange()
                .expectStatus().isOk()
                .expectBody(String.class).isEqualTo("Hello World");
    }

}

如果您只想专注于 web 层而不是开始一个完整的ApplicationContext,请考虑改用@WebMvcTest.

使用 Spring WebFlux 端点,您可以如下示例所示使用WebTestClient

@SpringBootTest
@AutoConfigureWebTestClient
class MyMockWebTestClientTests {

    @Test
    void exampleTest(@Autowired WebTestClient webClient) {
        webClient
            .get().uri("/")
            .exchange()
            .expectStatus().isOk()
            .expectBody(String.class).isEqualTo("Hello World");
    }

}

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

8.3.6. 使用正在运行的服务器进行测试

如果您需要启动一个完整运行的服务器,我们建议您使用随机端口。如果您使用@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT),则每次运行测试时都会随机选择一个可用端口。

@LocalServerPort注解可用于将实际使用的端口注入到您的测试中。为方便起见,需要对启动的服务器进行 REST 调用的测试可以通过额外添加@Autowire装配的WebTestClient,它解析到正在运行的服务器的相关链接,并带有用于验证响应的专用 API,如下例所示:

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class MyRandomPortWebTestClientTests {

    @Test
    void exampleTest(@Autowired WebTestClient webClient) {
        webClient
            .get().uri("/")
            .exchange()
            .expectStatus().isOk()
            .expectBody(String.class).isEqualTo("Hello World");
    }

}

WebTestClient可用于实时服务器和模拟环境

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

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class MyRandomPortTestRestTemplateTests {

    @Test
    void exampleTest(@Autowired TestRestTemplate restTemplate) {
        String body = restTemplate.getForObject("/", String.class);
        assertThat(body).isEqualTo("Hello World");
    }

}

8.3.7. 自定义 WebTestClient

要自定义WebTestClientbean,请配置一个WebTestClientBuilderCustomizerbean。任何此类 bean 都使用WebTestClient.Builder创建WebTestClient.

8.3.8. 使用 JMX

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

@ExtendWith(SpringExtension.class)
@SpringBootTest(properties = "spring.jmx.enabled=true")
@DirtiesContext
class MyJmxTests {

    @Autowired
    private MBeanServer mBeanServer;

    @Test
    void exampleTest() {
        assertThat(this.mBeanServer.getDomains()).contains("java.lang");
        // ...
    }

}

8.3.9. 使用指标

无论您的类路径如何,使用 @SpringBootTest 时,仪表注册表(内存中支持的除外)都不会自动配置。

如果您需要在集成测试中将指标导出到不同的后端,请使用@AutoConfigureMetrics.

8.3.10. 模拟和窥探 Bean

运行测试时,有时需要在应用程序上下文中模拟某些组件。例如,您可能有一些在开发期间不可用的远程服务的外观。当您想要模拟在真实环境中可能难以触发的故障时,模拟也很有用。

Spring Boot 包含一个@MockBean注解,可用于为您的ApplicationContext. 您可以使用注解添加新 bean 或替换单个现有 bean 定义。注解可以直接用于测试类、测试中的字段或@Configuration类和字段。在字段上使用时,创建的模拟实例也会被注入。在每个测试方法之后,模拟 bean 都会自动重置。

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

@ContextConfiguration(classes = MyConfig.class)
@TestExecutionListeners({ MockitoTestExecutionListener.class, ResetMocksTestExecutionListener.class })
class MyTests {

 // ...

}

以下示例将现有RemoteServicebean 替换为模拟实现:

@SpringBootTest
class MyTests {

    @Autowired
    private Reverser reverser;

    @MockBean
    private RemoteService remoteService;

    @Test
    void exampleTest() {
        given(this.remoteService.getValue()).willReturn("spring");
        String reverse = this.reverser.getReverseValue(); // Calls injected RemoteService
        assertThat(reverse).isEqualTo("gnirps");
    }

}

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

此外,您可以使用 @SpyBean 将任何现有的 beanMockito spy 包装在一起。有关完整详细信息,请参阅 Javadoc。

CGLib 代理,例如为作用域 bean 创建的代理,将代理方法声明为final. 这会阻止 Mockito 正常运行,因为它无法在其默认配置中模拟或监视final方法。如果您想模拟或监视这样的 bean,请将 Mockito 配置为通过org.mockito:mockito-inline添加到应用程序的测试依赖项来使用其内联模拟生成器。这允许 Mockito 模拟和监视final方法。
虽然 Spring 的测试框架在测试之间缓存应用程序上下文,并为共享相同配置的测试重用上下文,但使用@MockBean@SpyBean影响缓存键,这很可能会增加上下文的数量。
如果您使用@SpyBean通过名称引用参数的@Cacheable方法来监视 bean ,则您的应用程序必须使用-parameters. 这确保了一旦 bean 被监视,参数名称对缓存基础设施可用。
当您使用@SpyBean用于监视由 Spring 代理的 bean 时,您可能需要在某些情况下删除 Spring 的代理,例如在使用givenwhen设置期望值时。使用AopTestUtils.getTargetObject(yourProxiedSpy)也需要这样做。

8.3.11. 自动配置的测试

Spring Boot 的自动配置系统适用于应用程序,但有时对于测试来说有点太多了。它通常有助于仅加载测试应用程序“切面”所需的配置部分。例如,您可能想要测试 Spring MVC 控制器是否正确映射 URL,并且您不想在这些测试中涉及数据库调用,或者您可能想要测试 JPA 实体,而当这些测试运行。

spring-boot-test-autoconfigure模块包含许多注解,可用于自动配置此类“切面”。它们中的每一个都以类似的方式工作,它们中的每一个都以类似的方式工作,提供一个加载ApplicationContext@…Test 注解和一个或多个可用于自定义自动配置设置的@AutoConfigure…注解。

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

不支持通过在一个测试中使用多个@…Test注解来包含多个“切面” 。如果您需要多个“切面”,请选择其中一个@…Test注解并手动包含其他“切面”的@AutoConfigure…注解。

如果您对“切面”您的应用程序不感兴趣,但您想要一些自动配置的测试 bean,您也可以将@AutoConfigure…注解与标准@SpringBootTest注解一起使用。

8.3.12. 自动配置的 JSON 测试

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

  • JacksonObjectMapper,任何@JsonComponentbean和任何Jackson Module
  • Gson
  • Jsonb

可以在附录中找到启用@JsonTest的自动配置列表。

如果需要配置自动配置的元素,可以使用@AutoConfigureJsonTesters注解。

Spring Boot 包括基于 AssertJ 的帮助程序,它们与 JSONAssert 和 JsonPath 库一起检查 JSON 是否按预期显示。JacksonTesterGsonTesterBasicJsonTester类可分别用于 Jackson、Gson、Jsonb 和 Strings 。使用 @JsonTest 时,测试类上的任何辅助字段都可以是 @Autowired。. 以下示例显示了 Jackson 的测试类:

@JsonTest
class MyJsonTests {

    @Autowired
    private JacksonTester<VehicleDetails> json;

    @Test
    void serialize() throws Exception {
        VehicleDetails details = new VehicleDetails("Honda", "Civic");
        // Assert against a `.json` file in the same package as the test
        assertThat(this.json.write(details)).isEqualToJson("expected.json");
        // Or use JSON path based assertions
        assertThat(this.json.write(details)).hasJsonPathStringValue("@.make");
        assertThat(this.json.write(details)).extractingJsonPathStringValue("@.make").isEqualTo("Honda");
    }

    @Test
    void 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具体取决于类型。相反,您可以使用 AssertJsatisfies断言该值与给定条件是否匹配。例如,以下示例断言实际数字是否接近浮点值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)));
}

8.3.13. 自动配置的 Spring MVC 测试

要测试 Spring MVC 控制器是否按预期工作,请使用@WebMvcTest注解。 @WebMvcTest自动配置 Spring MVC 基础结构并将扫描的 bean 限制为@Controller, @ControllerAdvice, @JsonComponent, Converter, GenericConverter, Filter, HandlerInterceptor, WebMvcConfigurer,WebMvcRegistrationsHandlerMethodArgumentResolver. 使用注解@WebMvcTest 时不会扫描常规@Component@ConfigurationPropertiesbean。@EnableConfigurationProperties可用于包含@ConfigurationPropertiesbean。

在附录中找到 启用@WebMvcTest的自动配置设置列表。

如果您需要注册额外的组件,例如 Jackson Module,您可以通过在测试中使用@Import来导入额外的配置类。
通常,@WebMvcTest仅限于单个控制器,并与@MockBean结合使用,为所需的协作者提供模拟实现。

@WebMvcTest也可以自动配置MockMvc。Mock MVC 提供了一种强大的方法来快速测试 MVC 控制器,而无需启动完整的 HTTP 服务器。

您还可以在非@WebMvcTest中通过使用@AutoConfigureMockMvc注解来自动配置MockMvc(例如@SpringBootTest) 。以下示例使用MockMvc

@WebMvcTest(UserVehicleController.class)
class MyControllerTests {

    @Autowired
    private MockMvc mvc;

    @MockBean
    private UserVehicleService userVehicleService;

    @Test
    void 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 WebClientbean 和/或 Selenium WebDriverbean。以下示例使用 HtmlUnit:

@WebMvcTest(UserVehicleController.class)
class MyHtmlUnitTests {

    @Autowired
    private WebClient webClient;

    @MockBean
    private UserVehicleService userVehicleService;

    @Test
    void 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 将WebDriverbean 放在一个特殊的“域”中,以确保驱动程序在每次测试后退出并注入新实例。如果您不想要这种行为,您可以添加@Scope("singleton")到您的WebDriver @Bean定义中。
Spring Boot 创建的webDriver域将替换任何用户定义的同名域。如果您定义自己的webDriver域,您可能会发现在使用@WebMvcTest它会停止工作.
如果类路径上有 Spring Security,@WebMvcTest也会扫描WebSecurityConfigurerbean。您可以使用 Spring Security 的测试支持,而不是完全禁用此类测试的安全性。有关如何使用 Spring SecurityMockMvc支持的更多详细信息,请参见*howto.html* how-to 部分。

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

8.3.14. 自动配置的 Spring WebFlux 测试

要测试Spring WebFlux控制器是否按预期工作,您可以使用@WebFluxTest注解。 @WebFluxTest自动配置 Spring WebFlux 基础结构并将扫描的 bean 限制为@Controller@ControllerAdvice@JsonComponentConverterGenericConverterWebFilterWebFluxConfigurer. 使用注解@WebFluxTest 时不会扫描常规@Component@ConfigurationPropertiesbean。@EnableConfigurationProperties可用于包含@ConfigurationPropertiesbean。

可以在附录中找到 启用@WebFluxTest的自动配置列表。
如果您需要注册额外的组件,例如 Jackson Module,您可以在您的测试中 使用@Import导入额外的配置类。
通常,@WebFluxTest仅限于单个控制器并与@MockBean注解结合使用,为所需的协作者提供模拟实现。

@WebFluxTest还自动配置了 WebTestClient,它提供了一种强大的方法来快速测试 WebFlux 控制器,而无需启动完整的 HTTP 服务器。

您还可以在非@WebFluxTest中通过使用@AutoConfigureWebTestClient注解来自动配置WebTestClient(例如@SpringBootTest) 。以下示例使用WebTestClient@WebFluxTest

@WebFluxTest(UserVehicleController.class)
class MyControllerTests {

    @Autowired
    private WebTestClient webClient;

    @MockBean
    private UserVehicleService userVehicleService;

    @Test
    void 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 框架注册的路由。要在上下文中测试RouterFunctionbean,请考虑通过使用@Import或使用@SpringBootTest导入您自己的RouterFunction
@WebFluxTest无法检测作为@Bean类型注册的自定义安全配置SecurityWebFilterChain。要将其包含在您的测试中,您需要通过使用@Import或使用@SpringBootTest导入注册 bean 的配置。
有时编写 Spring WebFlux 测试是不够的;Spring Boot 可以帮助您使用实际的服务器运行完整的端到端测试

8.3.15。自动配置的 Spring GraphQL 测试

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

<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>

Gradle

dependencies {
    testImplementation("org.springframework.graphql:spring-graphql-test")
    // Unless already present in the implementation configuration
    testImplementation("org.springframework.boot:spring-boot-starter-webflux")
}

这个测试模块附带了GraphQlTester。测试仪在测试中大量使用,所以一定要熟悉使用它。有了GraphQlTester变体,Spring Boot 将根据测试类型自动配置它们:

  • ExecutionGraphQlServiceTester在服务器端执行测试,没有客户端也没有实际传输
  • 使用HttpGraphQlTester连接到服务器的客户端执行测试,有或没有服务器都可以

Spring Boot 可帮助您使用@GraphQlTest注解测试Spring GraphQL 控制器@GraphQlTest自动配置 Spring GraphQL 基础设施,不涉及任何传输或服务器。这会将扫描的bean 限制为@ControllerRuntimeWiringConfigurerJsonComponentConverterGenericConverterDataFetcherExceptionResolverInstrumentationGraphQlSourceBuilderCustomizer。使用注解@GraphQlTest时不会扫描常规@Component@ConfigurationPropertiesbean。@EnableConfigurationProperties可用于包含@ConfigurationPropertiesbean。

可以在附录中找到@GraphQlTest 启用的自动配置列表。

如果您需要注册额外的组件,例如 Jackson Module,您可以在您的测试中使用@Import导入额外的配置类。
通常,@GraphQlTest仅限于一组控制器并与@MockBean注解结合使用,为所需的协作者提供模拟实现。

@GraphQlTest(GreetingController.class)
class GreetingControllerTests {

    @Autowired
    private GraphQlTester graphQlTester;

    @Test
    void shouldGreetWithSpecificName() {
        this.graphQlTester.document("{ greeting(name: \"Alice\") } ").execute().path("greeting").entity(String.class)
                .isEqualTo("Hello, Alice!");
    }

    @Test
    void shouldGreetWithDefaultName() {
        this.graphQlTester.document("{ greeting } ").execute().path("greeting").entity(String.class)
                .isEqualTo("Hello, Spring!");
    }

}

@SpringBootTest测试是完整的集成测试,涉及整个应用程序。当使用随机或定义的端口时,会配置一个实时服务器并自动提供一个HttpGraphQlTester bean,以便您可以使用它来测试您的服务器。配置 MOCK 环境后,您还可以通过使用以下命令@AutoConfigureHttpGraphQlTester 注解测试类来请求HttpGraphQlTester bean :

@AutoConfigureHttpGraphQlTester
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
class GraphQlIntegrationTests {

    @Test
    void 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!");
    }

}

8.3.16. 自动配置的数据 Cassandra 测试

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

在附录中找到@DataCassandraTest启用的自动配置设置列表。

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

@DataCassandraTest
class MyDataCassandraTests {

    @Autowired
    private SomeRepository repository;

}

8.3.17. 自动配置的 Data Couchbase 测试

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

@DataCouchbaseTest在附录中找到 启用的自动配置设置列表。
以下示例显示了在 Spring Boot 中使用 Couchbase 测试的典型设置:

@DataCouchbaseTest
class MyDataCouchbaseTests {

    @Autowired
    private SomeRepository repository;

    // ...

}

8.3.18. 自动配置的数据 Elasticsearch 测试

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

在附录中找到 @DataElasticsearchTest启用的自动配置设置列表。
以下示例显示了在 Spring Boot 中使用 Elasticsearch 测试的典型设置:

@DataElasticsearchTest
class MyDataElasticsearchTests {

    @Autowired
    private SomeRepository repository;

    // ...

}

8.3.19. 自动配置的数据 JPA 测试

您可以使用@DataJpaTest注解来测试 JPA 应用程序。默认情况下,它会扫描@Entity类并配置 Spring Data JPA 存储库。如果类路径上有一个嵌入式数据库,它也会配置一个。默认情况下,通过将spring.jpa.show-sql属性设置为true来记录 SQL 查询。这可以使用showSql()注解的属性来禁用。

使用注解@DataJpaTest 时不会扫描常规@Component@ConfigurationPropertiesbean。@EnableConfigurationProperties可用于包含@ConfigurationProperties bean。

在附录中找到 @DataJpaTest启用的自动配置设置列表。
默认情况下,数据 JPA 测试是事务性的,并在每个测试结束时回滚。有关更多详细信息,请参阅 Spring Framework 参考文档中的相关部分。如果这不是您想要的,您可以为测试或整个班级禁用事务管理,如下所示:

@DataJpaTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
class MyNonTransactionalTests {

    // ...

}

数据 JPA 测试也可以注入一个bean,它提供了一个专门为测试设计TestEntityManager的标准 JPAEntityManager 的替代方案。
TestEntityManager也可以通过添加@AutoConfigureTestEntityManager自动配置到任何基于 Spring 的测试类。这样做时,请确保您的测试在事务中运行,例如通过添加@Transactional到您的测试类或方法。
如果您需要,也可以使用JdbcTemplate。以下示例显示了@DataJpaTest正在使用的注解:

@DataJpaTest
class MyRepositoryTests {

    @Autowired
    private TestEntityManager entityManager;

    @Autowired
    private UserRepository repository;

    @Test
    void 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注解,如以下示例所示:

@DataJpaTest
@AutoConfigureTestDatabase(replace = Replace.NONE)
class MyRepositoryTests {

    // ...

}

8.3.20. 自动配置的 JDBC 测试

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

可以在附录中找到@JdbcTest 启用的自动配置列表。
默认情况下,JDBC 测试是事务性的,并在每次测试结束时回滚。有关更多详细信息,请参阅 Spring Framework 参考文档中的相关部分。如果这不是您想要的,您可以为测试或整个班级禁用事务管理,如下所示:

@JdbcTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
class MyTransactionalTests {

}

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

8.3.21. 自动配置的数据 JDBC 测试

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

可以在附录中找到@DataJdbcTest启用的自动配置列表。
默认情况下,Data JDBC 测试是事务性的,并在每次测试结束时回滚。有关更多详细信息,请参阅 Spring Framework 参考文档中的相关部分。如果这不是您想要的,您可以禁用测试或整个测试类的事务管理,如JDBC 示例中所示

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

8.3.22。自动配置的 jOOQ 测试

您可以使用与@JdbcTest相似的方式使用@JooqTest进行jOOQ 相关测试。由于 jOOQ 严重依赖与数据库模式相对应的基于 Java 的模式,因此会使用现有DataSource。如果您想用内存数据库替换它,您可以使用@AutoConfigureTestDatabase覆盖这些设置。(有关在 Spring Boot 中使用 jOOQ 的更多信息,请参阅“ data.html ”。)使用注解@JooqTest 时不会扫描常规@Component@ConfigurationPropertiesbean。@EnableConfigurationProperties可用于包含@ConfigurationPropertiesbean。

可以在附录中找到@JooqTest 启用的自动配置列表。
@JooqTest配置一个DSLContext. 以下示例显示了@JooqTest正在使用的注解:

@JooqTest
class MyJooqTests {

    @Autowired
    private DSLContext dslContext;

    // ...

}

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

8.3.23. 自动配置数据 MongoDB 测试

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

@DataMongoTest在附录中找到 启用的自动配置设置列表。
下面的类显示了@DataMongoTest正在使用的注解:

@DataMongoTest
class MyDataMongoDbTests {

    @Autowired
    private MongoTemplate mongoTemplate;

    // ...

}

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

@DataMongoTest(excludeAutoConfiguration = EmbeddedMongoAutoConfiguration.class)
class MyDataMongoDbTests {

    // ...

}

8.3.24. 自动配置的数据 Neo4j 测试

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

在附录中找到 @DataNeo4jTest启用的自动配置设置列表。
以下示例显示了在 Spring Boot 中使用 Neo4J 测试的典型设置:

@DataNeo4jTest
class MyDataNeo4jTests {

    @Autowired
    private SomeRepository repository;

    // ...

}

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

@DataNeo4jTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
class MyDataNeo4jTests {

}

反应式访问不支持事务测试。如果您使用此样式,则必须按上述方式配置@DataNeo4jTest测试。

8.3.25. 自动配置的数据 Redis 测试

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

在附录中找到 @DataRedisTest启用的自动配置设置列表。
以下示例显示了@DataRedisTest正在使用的注解:

@DataRedisTest
class MyDataRedisTests {

    @Autowired
    private SomeRepository repository;

    // ...

}

8.3.26. 自动配置的数据 LDAP 测试

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

在附录中找到 @DataLdapTest启用的自动配置设置列表。
以下示例显示了@DataLdapTest正在使用的注解:

@DataLdapTest
class MyDataLdapTests {

    @Autowired
    private LdapTemplate ldapTemplate;

    // ...

}

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

@DataLdapTest(excludeAutoConfiguration = EmbeddedLdapAutoConfiguration.class)
class MyDataLdapTests {

    // ...

}

8.3.27. 自动配置的 REST 客户端

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

在附录中找到 @RestClientTest启用的自动配置设置列表。
您要测试的特定 bean 应使用@RestClientTestvaluecomponents属性指定,如以下示例所示:

@RestClientTest(RemoteVehicleDetailsService.class)
class MyRestClientTests {

    @Autowired
    private RemoteVehicleDetailsService service;

    @Autowired
    private MockRestServiceServer server;

    @Test
    void getVehicleDetailsWhenResultIsSuccessShouldReturnDetails() {
        this.server.expect(requestTo("/greet/details")).andRespond(withSuccess("hello", MediaType.TEXT_PLAIN));
        String greeting = this.service.callRestService();
        assertThat(greeting).isEqualTo("hello");
    }

}

8.3.28. 自动配置的 Spring REST 文档测试

您可以使用@AutoConfigureRestDocs注解在您的测试中使用Spring REST Docs与 Mock MVC、REST Assured 或 WebTestClient。它消除了 Spring REST Docs 中对 JUnit 扩展的需求。

@AutoConfigureRestDocs可用于覆盖默认输出目录(如果您使用 Maven 默认是target/generated-snippets或使用 Gradle默认为build/generated-snippets)。它还可用于配置出现在任何记录的 URI 中的主机、方案和端口。

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

在测试基于 servlet 的 Web 应用程序时可以使用@AutoConfigureRestDocs自定义MockMvcbean 以使用 Spring REST Docs。您可以像使用 Mock MVC 和 Spring REST Docs 时一样在测试中使用和使用它,如以下示例所示:

@WebMvcTest(UserController.class)
@AutoConfigureRestDocs
class MyUserDocumentationTests {

    @Autowired
    private MockMvc mvc;

    @Test
    void listUsers() throws Exception {
        this.mvc.perform(get("/users").accept(MediaType.TEXT_PLAIN))
            .andExpect(status().isOk())
            .andDo(document("list-users"));
    }

}

如果您需要对 Spring REST Docs 配置的控制比@AutoConfigureRestDocs的属性提供的更多,则可以使用RestDocsMockMvcConfigurationCustomizerbean,如以下示例所示:

@TestConfiguration(proxyBeanMethods = false)
public class MyRestDocsConfiguration implements RestDocsMockMvcConfigurationCustomizer {

    @Override
    public void customize(MockMvcRestDocumentationConfigurer configurer) {
        configurer.snippets().withTemplateFormat(TemplateFormats.markdown());
    }

}

如果你想利用 Spring REST Docs 对参数化输出目录的支持,你可以创建一个RestDocumentationResultHandlerbean。使用此结果处理程序进行自动配置调用alwaysDo,从而导致每个mockMvc调用自动生成默认片段。下面的例子显示了一个被定义的RestDocumentationResultHandler

@TestConfiguration(proxyBeanMethods = false)
public class MyResultHandlerConfiguration {

    @Bean
    public RestDocumentationResultHandler restDocumentation() {
        return MockMvcRestDocumentation.document("{method-name}");
    }

}
使用 WebTestClient 自动配置 Spring REST 文档测试

也可以在测试响应式 Web 应用程序的WebTestClient时使用@AutoConfigureRestDocs。您可以像使用 Spring REST Docs 时一样在测试中使用@WebFluxTest和使用@Autowired,如以下示例所示:

@WebFluxTest
@AutoConfigureRestDocs
class MyUsersDocumentationTests {

    @Autowired
    private WebTestClient webTestClient;

    @Test
    void listUsers() {
        this.webTestClient
            .get().uri("/")
        .exchange()
        .expectStatus()
            .isOk()
        .expectBody()
            .consumeWith(document("list-users"));
    }

}

如果您需要对 Spring REST Docs 配置的控制比 的属性提供的更多@AutoConfigureRestDocs,则可以使用RestDocsWebTestClientConfigurationCustomizerbean,如以下示例所示:

@TestConfiguration(proxyBeanMethods = false)
public class MyRestDocsConfiguration implements RestDocsWebTestClientConfigurationCustomizer {

    @Override
    public void customize(WebTestClientRestDocumentationConfigurer configurer) {
        configurer.snippets().withEncoding("UTF-8");
    }

}

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

@TestConfiguration(proxyBeanMethods = false)
public class MyWebTestClientBuilderCustomizerConfiguration {

    @Bean
    public WebTestClientBuilderCustomizer restDocumentation() {
        return (builder) -> builder.entityExchangeResultConsumer(document("{method-name}"));
    }

}
带有 REST Assured 的自动配置 Spring REST 文档测试

@AutoConfigureRestDocs使预配置为使用 Spring REST Docs 的RequestSpecification bean 可用于您的测试。您可以像使用 REST Assured 和 Spring REST Docs 时一样在测试中使用@Autowired和使用它,如以下示例所示:

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureRestDocs
class MyUserDocumentationTests {

    @Test
    void listUsers(@Autowired RequestSpecification documentationSpec, @LocalServerPort int port) {
        given(documentationSpec)
            .filter(document("list-users"))
        .when()
            .port(port)
            .get("/")
        .then().assertThat()
            .statusCode(is(200));
    }

}

如果您需要对 Spring REST Docs 配置的控制比@AutoConfigureRestDocs的属性提供的更多,则可以使用RestDocsRestAssuredConfigurationCustomizer bean,如以下示例所示:

@TestConfiguration(proxyBeanMethods = false)
public class MyRestDocsConfiguration implements RestDocsRestAssuredConfigurationCustomizer {

    @Override
    public void customize(RestAssuredRestDocumentationConfigurer configurer) {
        configurer.snippets().withTemplateFormat(TemplateFormats.markdown());
    }

}

8.3.29. 自动配置的 Spring Web 服务测试

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

您可以使用 @WebServiceClientTest 来测试使用 Spring Web Services 项目实现 Web 服务的应用程序。默认情况下,它配置一个模拟WebServiceServerbean 并自动自定义您的WebServiceTemplateBuilder. (有关在 Spring Boot 中使用 Web 服务的更多信息,请参阅“ io.html ”。)
在附录中找到@WebServiceClientTest 启用的自动配置设置列表。
以下示例显示了@WebServiceClientTest正在使用的注解:

@WebServiceClientTest(SomeWebService.class)
class MyWebServiceClientTests {

    @Autowired
    private MockWebServiceServer server;

    @Autowired
    private SomeWebService someWebService;

    @Test
    void 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 Services 项目实现 Web 服务的应用程序。默认情况下,它配置一个可用于调用 Web 服务端点的 MockWebServiceClientbean。(有关在 Spring Boot 中使用 Web 服务的更多信息,请参阅“ io.html ”。)
在附录中找到 @WebServiceServerTest启用的自动配置设置列表。
以下示例显示了@WebServiceServerTest正在使用的注解:

@WebServiceServerTest(ExampleEndpoint.class)
class MyWebServiceServerTests {

    @Autowired
    private MockWebServiceClient client;

    @Test
    void mockServerCall() {
        this.client
            .sendRequest(RequestCreators.withPayload(new StringSource("<ExampleRequest/>")))
            .andExpect(ResponseMatchers.payload(new StringSource("<ExampleResponse>42</ExampleResponse>")));
    }

}

8.3.30. 额外的自动配置和切面

每个切面提供一个或多个@AutoConfigure…注解,即定义应作为切面一部分包含的自动配置。通过创建自定义@AutoConfigure…注解或通过@ImportAutoConfiguration添加到测试中,可以逐个测试添加其他自动配置,如以下示例所示:

@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

您可以通过在此文件中使用#注解。

切片或@AutoConfigure …注释可以通过这种方式自定义,只要它使用@ImportAutoConfiguration进行元注释即可。

8.3.31. 用户配置和切面

如果您以合理的方式构建代码,则默认情况下您的@SpringBootApplication类将用作测试的配置。

然后,重要的是不要在应用程序的主类中乱扔特定于其功能特定区域的配置设置。

假设您使用的是 Spring Batch,并且您依赖于它的自动配置。您可以定义@SpringBootApplication如下:

@SpringBootApplication
@EnableBatchProcessing
public class MyApplication {

    // ...

}

因为这个类是测试的源配置,所以任何切面测试实际上都会尝试启动 Spring Batch,这绝对不是你想要做的。推荐的方法是将特定于区域的配置移动到与您的应用程序处于同一级别的单独@Configuration类中,如以下示例所示:

@Configuration(proxyBeanMethods = false)
@EnableBatchProcessing
public class MyBatchConfiguration {

    // ...

}

根据您的应用程序的复杂性,您可能有一个用于自定义的类或每个域区域一个@Configuration类。后一种方法允许您在其中一个测试中启用它,如有必要,使用@Import注解。有关何时可能希望为切面测试启用特定类的 @Configuration更多详细信息,请参阅此操作指南部分。
测试切面将@Configuration类排除在扫描之外。例如,对于 @WebMvcTest,以下配置不会在测试切面加载的应用程序上下文中包含给定的WebMvcConfigurer bean:

@Configuration(proxyBeanMethods = false)
public class MyWebConfiguration {

    @Bean
    public WebMvcConfigurer testConfigurer() {
        return new WebMvcConfigurer() {
            // ...
        };
    }

}

但是,下面的配置将导致自定义WebMvcConfigurer被测试切面加载。

@Component
public class MyWebMvcConfigurer implements WebMvcConfigurer {

    // ...

}

另一个混淆来源是类路径扫描。假设,当您以合理的方式构建代码时,您需要扫描一个额外的包。您的应用程序可能类似于以下代码:

@SpringBootApplication
@ComponentScan({ "com.example.app", "com.example.another" })
public class MyApplication {

    // ...

}

这样做有效地覆盖了默认的组件扫描指令,其副作用是扫描这两个包,而不管您选择的切面是什么。例如,a@DataJpaTest似乎突然扫描应用程序的组件和用户配置。同样,将自定义指令移动到单独的类是解决此问题的好方法。

如果这不是您的选择,您可以@SpringBootConfiguration在测试的层次结构中创建一个位置,以便使用它。或者,您可以为您的测试指定一个源,这将禁用查找默认源的行为。

8.3.32. 使用 Spock 测试 Spring Boot 应用程序

Spock 2.x 可用于测试 Spring Boot 应用程序。为此,请将 Spockspock-spring模块的依赖项添加到应用程序的构建中。 spock-spring将 Spring 的测试框架集成到 Spock 中。有关详细信息,请参阅Spock 的 Spring 模块的文档

8.4. 测试工具

测试应用程序时通常有用的一些测试实用程序类被打包为spring-boot.

8.4.1. ConfigDataApplicationContextInitializer

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

@ContextConfiguration(classes = Config.class, initializers = ConfigDataApplicationContextInitializer.class)
class MyConfigFileTests {

    // ...

}

单独使用ConfigDataApplicationContextInitializer不支持@Value("${…}")注入。它唯一的工作是确保将application.properties文件加载到 Spring 的Environment. 为了获得@Value支持,您需要另外配置 PropertySourcesPlaceholderConfigurer@SpringBootTest,它会为您自动配置一个。

8.4.2. 测试属性值

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

class MyEnvironmentTests {

    @Test
    void testPropertySources() {
        MockEnvironment environment = new MockEnvironment();
        TestPropertyValues.of("org=Spring", "name=Boot").applyTo(environment);
        assertThat(environment.getProperty("name")).isEqualTo("Boot");
    }

}

8.4.3. 输出捕获

OutputCapture是一个可用于捕获System.outSystem.err输出的 JUnit Extension。要使用它,需要添加@ExtendWith(OutputCaptureExtension.class)和 injectionCapturedOutput作为测试类构造函数或测试方法的参数,如下所示:

@ExtendWith(OutputCaptureExtension.class)
class MyOutputCaptureTests {

    @Test
    void testName(CapturedOutput output) {
        System.out.println("Hello World!");
        assertThat(output).contains("World");
    }

}

8.4.4. 测试RestTemplate

TestRestTemplate是 Spring 的一种方便替代方案,RestTemplate在集成测试中很有用。您可以获得一个普通模板或发送基本 HTTP 身份验证(带有用户名和密码)的模板。在任何一种情况下,模板都是容错的。这意味着它以一种测试友好的方式运行,不会在 4xx 和 5xx 错误上抛出异常。相反,可以通过返回ResponseEntity的及其状态码检测此类错误。

Spring Framework 5.0 提供了一个新功能WebTestClient,适用于WebFlux 集成测试以及WebFlux 和 MVC 端到端测试。与TestRestTemplate不同,它提供了流式的api.
建议使用 Apache HTTP 客户端(版本 4.3.2 或更高版本),但不是强制性的。如果您的类路径中有它,则通过适当地配置客户端来或的TestRestTemplate响应。如果您确实使用 Apache 的 HTTP 客户端,则会启用一些额外的测试友好功能:

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

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

class MyTests {

    private final TestRestTemplate template = new TestRestTemplate();

    @Test
    void testRequest() {
        ResponseEntity<String> headers = this.template.getForEntity("https://myhost.example.com/example", String.class);
        assertThat(headers.getHeaders().getLocation()).hasHost("other.example.com");
    }

}

或者,如果您将@SpringBootTest注解与WebEnvironment.RANDOM_PORTWebEnvironment.DEFINED_PORT一起使用,您可以注入一个完全配置的TestRestTemplate并开始使用它。如有必要,可以通过RestTemplateBuilderbean 应用额外的定制。任何未指定主机和端口的 URL 都会自动连接到嵌入式服务器,如下例所示:

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class MySpringBootTests {

    @Autowired
    private TestRestTemplate template;

    @Test
    void testRequest() {
        HttpHeaders headers = this.template.getForEntity("/example", String.class).getHeaders();
        assertThat(headers.getLocation()).hasHost("other.example.com");
    }

    @TestConfiguration(proxyBeanMethods = false)
    static class RestTemplateBuilderConfiguration {

        @Bean
        RestTemplateBuilder restTemplateBuilder() {
            return new RestTemplateBuilder().setConnectTimeout(Duration.ofSeconds(1))
                    .setReadTimeout(Duration.ofSeconds(1));
        }

    }

}
0

评论区