文章摘要(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:hamcrest
的hamcrest-core
被排除在外,那是spring-boot-starter-test
的一部分。
8.1. 测试范围依赖
“ spring-boot-starter-test
Starter”(在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
不会启动服务器。您可以使用@SpringBootTest
的webEnvironment
属性来进一步优化测试的运行方式:
MOCK
(默认):加载webApplicationContext
并提供模拟网络环境。使用此注解时不启动嵌入式服务器。如果您的类路径上没有可用的 Web 环境,则此模式会透明地回退到创建常规的 non-webApplicationContext
。它可以与您的 Web 应用程序结合使用@AutoConfigureMockMvc
或@AutoConfigureWebTestClient
用于基于模拟的测试。RANDOM_PORT
: 加载WebServerApplicationContext
并提供一个真实的网络环境。嵌入式服务器会启动并侦听随机端口。DEFINED_PORT
: 加载WebServerApplicationContext
并提供一个真实的网络环境。嵌入式服务器会启动并侦听定义的端口(来自您的application.properties
)或默认的8080
端口.NONE
:通过使用SpringApplication
加载一个ApplicationContext
但不提供任何Web 环境(模拟或其他)。
如果您的测试是
@Transactional
,默认情况下,它会在每个测试方法结束时回滚事务。然而,由于使用RANDOM_PORT
或DEFINED_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,您可以使用@SpringBootTest
的args
属性注入它们。
@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
要自定义WebTestClient
bean,请配置一个WebTestClientBuilderCustomizer
bean。任何此类 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 { // ... }
以下示例将现有RemoteService
bean 替换为模拟实现:
@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
将任何现有的 bean
与 Mockito 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 的代理,例如在使用given
或when
设置期望值时。使用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 映射器,它可以是以下库之一:
- Jackson
ObjectMapper
,任何@JsonComponent
bean和任何JacksonModule
的 Gson
Jsonb
可以在附录中找到启用
@JsonTest
的自动配置列表。
如果需要配置自动配置的元素,可以使用@AutoConfigureJsonTesters
注解。
Spring Boot 包括基于 AssertJ 的帮助程序,它们与 JSONAssert 和 JsonPath 库一起检查 JSON 是否按预期显示。JacksonTester
、GsonTester
和BasicJsonTester
类可分别用于 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
,WebMvcRegistrations
和HandlerMethodArgumentResolver
. 使用注解@WebMvcTest
时不会扫描常规@Component
和@ConfigurationProperties
bean。@EnableConfigurationProperties
可用于包含@ConfigurationProperties
bean。
可在附录中找到 启用@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 WebClient
bean 和/或 Selenium WebDriver
bean。以下示例使用 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 将
WebDriver
bean 放在一个特殊的“域”中,以确保驱动程序在每次测试后退出并注入新实例。如果您不想要这种行为,您可以添加@Scope("singleton")
到您的WebDriver
@Bean
定义中。
Spring Boot 创建的webDriver
域将替换任何用户定义的同名域。如果您定义自己的webDriver
域,您可能会发现在使用@WebMvcTest
它会停止工作.
如果类路径上有 Spring Security,@WebMvcTest
也会扫描WebSecurityConfigurer
bean。您可以使用 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
、@JsonComponent
、Converter
、GenericConverter
、WebFilter
和WebFluxConfigurer
. 使用注解@WebFluxTest
时不会扫描常规@Component
和@ConfigurationProperties
bean。@EnableConfigurationProperties
可用于包含@ConfigurationProperties
bean。
可以在附录中找到 启用@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 框架注册的路由。要在上下文中测试RouterFunction
bean,请考虑通过使用@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 限制为@Controller
、RuntimeWiringConfigurer
、JsonComponent
、Converter
、GenericConverter
、DataFetcherExceptionResolver
、Instrumentation
和GraphQlSourceBuilderCustomizer
。使用注解@GraphQlTest
时不会扫描常规@Component
和@ConfigurationProperties
bean。@EnableConfigurationProperties
可用于包含@ConfigurationProperties
bean。
可以在附录中找到@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
和@ConfigurationProperties
bean。@EnableConfigurationProperties
可用于包含@ConfigurationProperties
bean。(有关在 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
和@ConfigurationProperties
bean。@EnableConfigurationProperties
可用于包含@ConfigurationProperties
bean。(有关在 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
和@ConfigurationProperties
bean。@EnableConfigurationProperties
可用于包含@ConfigurationProperties
bean。(有关在 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
和@ConfigurationProperties
bean。@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
和@ConfigurationProperties
bean。@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
和@ConfigurationProperties
bean。 @EnableConfigurationProperties
可用于包含@ConfigurationProperties
bean。
可以在附录中找到@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
和@ConfigurationProperties
bean。@EnableConfigurationProperties
可用于包含@ConfigurationProperties
bean。
可以在附录中找到@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
和@ConfigurationProperties
bean。@EnableConfigurationProperties
可用于包含@ConfigurationProperties
bean。(有关在 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
和@ConfigurationProperties
bean。@EnableConfigurationProperties
可用于包含@ConfigurationProperties
bean。(有关在 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
和@ConfigurationProperties
bean。@EnableConfigurationProperties
可用于包含@ConfigurationProperties
bean。。(有关在 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
和@ConfigurationProperties
bean。@EnableConfigurationProperties
可用于包含@ConfigurationProperties
bean。(有关在 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
和@ConfigurationProperties
bean。@EnableConfigurationProperties
可用于包含@ConfigurationProperties
bean。
可在附录中找到 @RestClientTest
启用的自动配置设置列表。
您要测试的特定 bean 应使用@RestClientTest
的value
或components
属性指定,如以下示例所示:
@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
自定义MockMvc
bean 以使用 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
的属性提供的更多,则可以使用RestDocsMockMvcConfigurationCustomizer
bean,如以下示例所示:
@TestConfiguration(proxyBeanMethods = false)
public class MyRestDocsConfiguration implements RestDocsMockMvcConfigurationCustomizer {
@Override
public void customize(MockMvcRestDocumentationConfigurer configurer) {
configurer.snippets().withTemplateFormat(TemplateFormats.markdown());
}
}
如果你想利用 Spring REST Docs 对参数化输出目录的支持,你可以创建一个RestDocumentationResultHandler
bean。使用此结果处理程序进行自动配置调用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
,则可以使用RestDocsWebTestClientConfigurationCustomizer
bean,如以下示例所示:
@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 服务的应用程序。默认情况下,它配置一个模拟WebServiceServer
bean 并自动自定义您的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 服务端点的 MockWebServiceClient
bean。(有关在 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
让您快速将属性添加到 ConfigurableEnvironment
或ConfigurableApplicationContext
. 您可以使用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.out
和System.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_PORT
或WebEnvironment.DEFINED_PORT
一起使用,您可以注入一个完全配置的TestRestTemplate
并开始使用它。如有必要,可以通过RestTemplateBuilder
bean 应用额外的定制。任何未指定主机和端口的 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));
}
}
}
评论区