测试 Spring Boot 应用
Spring Boot应用就是Spring应用上下文所以测试它不需要做太多特别的作,除了你通常在原版春季环境中所做的那样。
Spring Boot 的外部属性、日志和其他功能默认仅在使用SpringApplication去创造它。 |
Spring靴提供了@SpringBootTest注释,可以作为标准的替代方案春季测试 @ContextConfiguration需要 Spring Boot 功能时的注释。
注释的工作原理是创建 应用上下文在你的测试中使用了SpringApplication.
此外@SpringBootTest还提供了许多其他注释,用于测试应用更具体的切片。
如果你用的是JUnit 4,别忘了补充@RunWith(SpringRunner.class)对你的测试进行,否则注释会被忽略。
如果你用的是JUnit 6,就不需要添加对应的@ExtendWith(SpringExtension.class)如@SpringBootTest以及另一个@…测试注释已经用它做了注释。 |
默认情况下,@SpringBootTest不会启动服务器。
你可以使用webEnvironment属性@SpringBootTest进一步优化测试运行方式:
-
模拟(默认):加载一张蛛网应用上下文并提供了模拟网页环境。 使用该注释时,嵌入式服务器不会被启动。 如果你的类路径上没有网页环境,这个模式会透明地退回到创建一个普通的非网页应用上下文. 它可以与@AutoConfigureMockMvc或@AutoConfigureWebTestClient用于基于模拟的网络应用测试。 -
RANDOM_PORT:装载WebServerApplicationContext并提供了真实的网络环境。 嵌入式服务器启动后,随机端口监听。 -
DEFINED_PORT:装载WebServerApplicationContext并提供了真实的网络环境。 嵌入式服务器启动后,会在定义的端口(来自你的application.properties)或在默认的8080. -
没有:加载了应用上下文通过SpringApplication但不提供任何网页环境(无论是模拟还是其他)。
如果你的测试是@Transactional默认情况下,它会在每个测试方法结束时回滚该事务。
然而,使用该安排时,任一RANDOM_PORT或DEFINED_PORT隐式地提供了真正的 servlet 环境,HTTP 客户端和服务器运行在不同的线程中,因此也属于不同的事务。
在这种情况下,服务器上发起的任何事务都不会回滚。 |
@SpringBootTest跟webEnvironment = WebEnvironment.RANDOM_PORT如果你的应用用的是管理服务器的不同端口,管理服务器也会在一个随机端口上启动。 |
检测网页应用类型
如果有 Spring MVC,则会配置一个常规的基于 MVC 的应用上下文。 如果你只有 Spring WebFlux,我们会检测到它并配置基于 WebFlux 的应用上下文。
如果两者同时存在,春季MVC优先。
如果你想在这种情况下测试响应式网页应用,必须设置spring.main.web-application-type财产:
-
Java
-
Kotlin
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest(properties = "spring.main.web-application-type=reactive")
class MyWebFluxTests {
// ...
}
import org.springframework.boot.test.context.SpringBootTest
@SpringBootTest(properties = ["spring.main.web-application-type=reactive"])
class MyWebFluxTests {
// ...
}
检测测试配置
如果你熟悉 Spring 测试框架,可能已经习惯了使用@ContextConfiguration(类=...)以指定哪个Spring@Configuration装载。
或者,你可能经常用嵌套@Configuration考试中的课程。
在测试 Spring Boot 应用时,通常不需要这样做。
Spring靴@*测试注释会自动搜索你未明确定义的主要配置时。
搜索算法从包含该测试的包出发,直到找到一个标注为@SpringBootApplication或@SpringBootConfiguration.
只要你把代码结构合理,通常就能找到你的主要配置。
|
如果你用测试注释来测试应用中更具体的切片,应避免在主方法的应用类中添加针对特定区域的配置设置。 底层组件扫描配置 |
如果你想自定义主配置,可以用嵌套配置@TestConfiguration类。
不像嵌套@Configuration类,将用来替代你应用的主要配置,嵌套@TestConfiguration类是除了应用的主配置之外的。
| Spring的测试框架在测试之间缓存应用上下文。 因此,只要你的测试配置相同(无论如何被发现),加载上下文的耗时过程只会发生一次。 |
使用测试配置主方法
通常测试配置为@SpringBootTest将是你的主角色@SpringBootApplication.
在大多数结构良好的应用中,该配置类还会包括主要启动应用程序的方法。
例如,以下是典型 Spring Boot 应用中非常常见的代码模式:
-
Java
-
Kotlin
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);
}
}
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.docs.using.structuringyourcode.locatingthemainclass.MyApplication
import org.springframework.boot.runApplication
@SpringBootApplication
class MyApplication
fun main(args: Array<String>) {
runApplication<MyApplication>(*args)
}
在上述示例中,该主要方法除了委派给SpringApplication.run(Class, String...).
不过,也可以有更复杂的主要调用前应用自定义的方法SpringApplication.run(Class, String...).
例如,这里有一个应用可以更改横幅模式并设置额外的配置文件:
-
Java
-
Kotlin
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);
}
}
import org.springframework.boot.Banner
import org.springframework.boot.runApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
@SpringBootApplication
class MyApplication
fun main(args: Array<String>) {
runApplication<MyApplication>(*args) {
setBannerMode(Banner.Mode.OFF)
setAdditionalProfiles("myprofile")
}
}
由于在主要方法可以影响得到的应用上下文你可能还想使用主要创建应用上下文用在你的测试中。
默认情况下,@SpringBootTest不会打电话给你的主要方法,而该类本身直接用于创建应用上下文
如果你想改变这种行为,你可以更改useMainMethod属性@SpringBootTest自SpringBootTest.UseMainMethod.ALWAYS或SpringBootTest.UseMainMethod.WHEN_AVAILABLE.
当设置为总是,如果不是,则检验失败主要方法可以找到。
当设置为WHEN_AVAILABLE这主要如果有方法,将采用,否则将采用标准加载机制。
-
Java
-
Kotlin
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 {
@Test
void exampleTest() {
// ...
}
}
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 {
@Test
fun exampleTest() {
// ...
}
}
排除测试配置
如果你的应用使用组件扫描(例如,如果你使用@SpringBootApplication或@ComponentScan你可能会发现,你只为特定测试创建的顶级配置类会被无意中发现。
正如我们之前所见,@TestConfiguration可用于测试的内类以定制主配置。@TestConfiguration也可以用于顶级类。这样做表示该类别不应通过扫描获得。
然后你可以在需要的地方显式导入该类,如下示例所示:
-
Java
-
Kotlin
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 {
@Test
void exampleTest() {
// ...
}
}
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 {
@Test
fun exampleTest() {
// ...
}
}
如果你直接使用@ComponentScan(也就是说,不是通过@SpringBootApplication你需要注册TypeExclusionFilter带着它。
参见TypeExclusionFilter详细信息请参考API文档。 |
一艘进口的@TestConfiguration在内类之前处理@TestConfiguration以及一艘进口的@TestConfiguration在通过组件扫描找到任何配置之前,都会被处理。
一般来说,这种排序差异没有明显影响,但如果你依赖豆子覆盖,这一点需要注意。 |
应用参数的使用
如果你的应用需要参数,你可以
有@SpringBootTest用args属性。
-
Java
-
Kotlin
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 {
@Test
void applicationArgumentsPopulated(@Autowired ApplicationArguments args) {
assertThat(args.getOptionNames()).containsOnly("app.test");
assertThat(args.getOptionValues("app.test")).containsOnly("one");
}
}
import org.assertj.core.api.Assertions.assertThat
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
@SpringBootTest(args = ["--app.test=one"])
class MyApplicationArgumentTests {
@Test
fun applicationArgumentsPopulated(@Autowired args: ApplicationArguments) {
assertThat(args.optionNames).containsOnly("app.test")
assertThat(args.getOptionValues("app.test")).containsOnly("one")
}
}
在模拟环境中测试
默认情况下,@SpringBootTest不启动服务器,而是搭建一个模拟环境用于测试网页端点。
通过 Spring MVC,我们可以用以下方式查询我们的网页端点莫克麦克.
以下集成方案可用:
-
常规
莫克麦克它使用了Hamcrest。 -
MockMvcTester结束了莫克麦克并使用 AssertJ。 -
RestTestClient哪里莫克麦克作为服务器接入,用于处理请求。 -
WebTestClient哪里莫克麦克作为服务器接入,用于处理请求。
以下示例展示了可用的集成方式:
-
Java
-
Kotlin
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.resttestclient.autoconfigure.AutoConfigureRestTestClient;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
import org.springframework.boot.webtestclient.autoconfigure.AutoConfigureWebTestClient;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.assertj.MockMvcTester;
import org.springframework.test.web.servlet.client.RestTestClient;
import org.springframework.test.web.servlet.client.RestTestClient.ResponseSpec;
import org.springframework.test.web.servlet.client.assertj.RestTestClientResponse;
import static org.assertj.core.api.Assertions.assertThat;
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
@AutoConfigureRestTestClient
@AutoConfigureWebTestClient
class MyMockMvcTests {
@Test
void testWithMockMvc(@Autowired MockMvc mvc) throws Exception {
mvc.perform(get("/"))
.andExpect(status().isOk())
.andExpect(content().string("Hello World"));
}
@Test // If AssertJ is on the classpath, you can use MockMvcTester
void testWithMockMvcTester(@Autowired MockMvcTester mvc) {
assertThat(mvc.get().uri("/"))
.hasStatusOk()
.hasBodyTextEqualTo("Hello World");
}
@Test
void testWithRestTestClient(@Autowired RestTestClient webClient) {
webClient
.get().uri("/")
.exchange()
.expectStatus().isOk()
.expectBody(String.class).isEqualTo("Hello World");
}
@Test // If you prefer AssertJ, dedicated assertions are available
void testWithRestTestClientAssertJ(@Autowired RestTestClient webClient) {
ResponseSpec spec = webClient.get().uri("/").exchange();
RestTestClientResponse response = RestTestClientResponse.from(spec);
assertThat(response).hasStatusOk()
.bodyText().isEqualTo("Hello World");
}
@Test // If Spring WebFlux is on the classpath
void testWithWebTestClient(@Autowired WebTestClient webClient) {
webClient
.get().uri("/")
.exchange()
.expectStatus().isOk()
.expectBody(String.class).isEqualTo("Hello World");
}
}
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.resttestclient.autoconfigure.AutoConfigureRestTestClient
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc
import org.springframework.boot.webtestclient.autoconfigure.AutoConfigureWebTestClient
import org.springframework.test.web.reactive.server.WebTestClient
import org.springframework.test.web.reactive.server.expectBody
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.assertj.MockMvcTester
import org.springframework.test.web.servlet.client.RestTestClient
import org.springframework.test.web.servlet.client.assertj.RestTestClientResponse
import org.springframework.test.web.servlet.client.expectBody
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.content
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status
@SpringBootTest
@AutoConfigureMockMvc
@AutoConfigureRestTestClient
@AutoConfigureWebTestClient
class MyMockMvcTests {
@Test
fun testWithMockMvc(@Autowired mvc: MockMvc) {
mvc.perform(get("/"))
.andExpect(status().isOk())
.andExpect(content().string("Hello World"))
}
@Test // If AssertJ is on the classpath, you can use MockMvcTester
fun testWithMockMvcTester(@Autowired mvc: MockMvcTester) {
assertThat(mvc.get().uri("/")).hasStatusOk()
.hasBodyTextEqualTo("Hello World")
}
@Test
fun testWithRestTestClient(@Autowired webClient: RestTestClient) {
webClient
.get().uri("/")
.exchange()
.expectStatus().isOk
.expectBody<String>().isEqualTo("Hello World")
}
@Test // If you prefer AssertJ, dedicated assertions are available
fun testWithRestTestClientAssertJ(@Autowired webClient: RestTestClient) {
val spec = webClient.get().uri("/").exchange()
val response = RestTestClientResponse.from(spec)
assertThat(response).hasStatusOk().bodyText().isEqualTo("Hello World")
}
@Test // If Spring WebFlux is on the classpath
fun testWithWebTestClient(@Autowired webClient: WebTestClient) {
webClient
.get().uri("/")
.exchange()
.expectStatus().isOk
.expectBody<String>().isEqualTo("Hello World")
}
}
如果你只想专注于网页层,不想开始完整的应用上下文,考虑使用 @WebMvcTest相反。 |
通过 Spring WebFlux 终端,你可以使用WebTestClient如下例所示:
-
Java
-
Kotlin
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.webtestclient.autoconfigure.AutoConfigureWebTestClient;
import org.springframework.test.web.reactive.server.WebTestClient;
@SpringBootTest
@AutoConfigureWebTestClient
class MyMockWebTestClientTests {
@Test
void exampleTest(@Autowired WebTestClient webClient) {
webClient
.get().uri("/")
.exchange()
.expectStatus().isOk()
.expectBody(String.class).isEqualTo("Hello World");
}
}
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.webtestclient.autoconfigure.AutoConfigureWebTestClient
import org.springframework.test.web.reactive.server.WebTestClient
import org.springframework.test.web.reactive.server.expectBody
@SpringBootTest
@AutoConfigureWebTestClient
class MyMockWebTestClientTests {
@Test
fun exampleTest(@Autowired webClient: WebTestClient) {
webClient
.get().uri("/")
.exchange()
.expectStatus().isOk
.expectBody<String>().isEqualTo("Hello World")
}
}
|
在模拟环境中测试通常比使用完整的 servlet 容器更快。 然而,由于模拟发生在 Spring MVC 层,依赖底层 servlet 容器行为的代码无法直接用 MockMvc 测试。 例如,Spring Boot 的错误处理基于 servlet 容器提供的“错误页面”支持。 这意味着,虽然你可以测试 MVC 层的抛出和异常处理,但不能直接测试特定的自定义错误页面是否被渲染出来。 如果你需要测试这些低层问题,可以按照下一节的描述启动一个完全运行的服务器。 |
运行中的服务器测试
如果你需要启动一个完整运行的服务器,我们建议你使用随机端口。
如果你使用,@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)每次测试运行时,随机选择一个可用端口。
这@LocalServerPort注释可以用来注入实际使用的端口到你的测试中。
需要向启动服务器发送 REST 调用的测试可以自动接线RestTestClient通过对测试类进行注释,记载为@AutoConfigureRestTestClient.
配置后的客户端解析与运行服务器的相对链接,并配备专用 API 用于验证响应,如下示例所示:
-
Java
-
Kotlin
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.resttestclient.autoconfigure.AutoConfigureRestTestClient;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.test.web.servlet.client.RestTestClient;
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureRestTestClient
class MyRandomPortRestTestClientTests {
@Test
void exampleTest(@Autowired RestTestClient webClient) {
webClient
.get().uri("/")
.exchange()
.expectStatus().isOk()
.expectBody(String.class).isEqualTo("Hello World");
}
}
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.resttestclient.autoconfigure.AutoConfigureRestTestClient
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment
import org.springframework.test.web.servlet.client.RestTestClient
import org.springframework.test.web.servlet.client.expectBody
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureRestTestClient
class MyRandomPortRestTestClientTests {
@Test
fun exampleTest(@Autowired webClient: RestTestClient) {
webClient
.get().uri("/")
.exchange()
.expectStatus().isOk
.expectBody<String>().isEqualTo("Hello World")
}
}
如果你更喜欢使用 AssertJ,可以从以下平台获得专门的断言RestTest客户端响应如下例所示:
-
Java
-
Kotlin
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.resttestclient.autoconfigure.AutoConfigureRestTestClient;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.test.web.servlet.client.RestTestClient;
import org.springframework.test.web.servlet.client.RestTestClient.ResponseSpec;
import org.springframework.test.web.servlet.client.assertj.RestTestClientResponse;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureRestTestClient
class MyRandomPortRestTestClientAssertJTests {
@Test
void exampleTest(@Autowired RestTestClient webClient) {
ResponseSpec spec = webClient.get().uri("/").exchange();
RestTestClientResponse response = RestTestClientResponse.from(spec);
assertThat(response).hasStatusOk().bodyText().isEqualTo("Hello World");
}
}
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.resttestclient.autoconfigure.AutoConfigureRestTestClient
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment
import org.springframework.test.web.servlet.client.RestTestClient
import org.springframework.test.web.servlet.client.assertj.RestTestClientResponse
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureRestTestClient
class MyRandomPortRestTestClientAssertJTests {
@Test
fun exampleTest(@Autowired webClient: RestTestClient) {
val exchange = webClient.get().uri("/").exchange()
val response = RestTestClientResponse.from(exchange)
assertThat(response).hasStatusOk()
.bodyText().isEqualTo("Hello World")
}
}
如果你有春季网流在类路径上,你也可以自动接线 AWebTestClient通过对测试类进行注释,记载为@AutoConfigureWebTestClient.
WebTestClient提供了类似的API,如下示例所示:
-
Java
-
Kotlin
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.webtestclient.autoconfigure.AutoConfigureWebTestClient;
import org.springframework.test.web.reactive.server.WebTestClient;
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureWebTestClient
class MyRandomPortWebTestClientTests {
@Test
void exampleTest(@Autowired WebTestClient webClient) {
webClient
.get().uri("/")
.exchange()
.expectStatus().isOk()
.expectBody(String.class).isEqualTo("Hello World");
}
}
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.webtestclient.autoconfigure.AutoConfigureWebTestClient
import org.springframework.test.web.reactive.server.WebTestClient
import org.springframework.test.web.reactive.server.expectBody
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureWebTestClient
class MyRandomPortWebTestClientTests {
@Test
fun exampleTest(@Autowired webClient: WebTestClient) {
webClient
.get().uri("/")
.exchange()
.expectStatus().isOk
.expectBody<String>().isEqualTo("Hello World")
}
}
WebTestClient也可以与模拟环境一起使用,无需运行服务器,只需注释你的测试类@AutoConfigureWebTestClient从春开网通量测试. |
这spring-boot-resttestclient模块还提供测试休息模板设备:
-
Java
-
Kotlin
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.resttestclient.TestRestTemplate;
import org.springframework.boot.resttestclient.autoconfigure.AutoConfigureTestRestTemplate;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureTestRestTemplate
class MyRandomPortTestRestTemplateTests {
@Test
void exampleTest(@Autowired TestRestTemplate restTemplate) {
String body = restTemplate.getForObject("/", String.class);
assertThat(body).isEqualTo("Hello World");
}
}
import org.assertj.core.api.Assertions.assertThat
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.resttestclient.TestRestTemplate
import org.springframework.boot.resttestclient.autoconfigure.AutoConfigureTestRestTemplate
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureTestRestTemplate
class MyRandomPortTestRestTemplateTests {
@Test
fun exampleTest(@Autowired restTemplate: TestRestTemplate) {
val body = restTemplate.getForObject("/", String::class.java)
assertThat(body).isEqualTo("Hello World")
}
}
定制 RestTestClient
以定制RestTestClient豆子,配置一个RestTestClientBuilderCustomizer豆。
任何这样的豆子都称为RestTestClient.Builder用于创建RestTestClient.
定制WebTestClient
以定制WebTestClient豆子,配置一个WebTestClientBuilderCustomizer豆。
任何这样的豆子都称为WebTestClient.Builder用于创建WebTestClient.
使用 JMX
由于测试上下文框架缓存上下文,JMX默认被禁用,以防止相同组件在同一域注册。
如果该测试需要访问MBeanServer也可以考虑标记脏污:
-
Java
-
Kotlin
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 {
@Autowired
private MBeanServer mBeanServer;
@Test
void exampleTest() {
assertThat(this.mBeanServer.getDomains()).contains("java.lang");
// ...
}
}
import javax.management.MBeanServer
import org.assertj.core.api.Assertions.assertThat
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
@SpringBootTest(properties = ["spring.jmx.enabled=true"])
@DirtiesContext
class MyJmxTests(@Autowired val mBeanServer: MBeanServer) {
@Test
fun exampleTest() {
assertThat(mBeanServer.domains).contains("java.lang")
// ...
}
}
利用观察
如果你在切片测试中注释为@AutoConfigureTracing从Spring靴-微尺-追踪-测试或@AutoConfigureMetrics从Spring靴-微米-公制-测试,它会自动配置一个ObservationRegistry.
使用度量
无论你的类路径是什么,除了内存备份的表注册表外,使用时都不会被自动配置@SpringBootTest.
如果你需要将指标导出到其他后端作为集成测试的一部分,可以用@AutoConfigureMetrics.
如果你在切片测试中注释为@AutoConfigureMetrics它会自动配置内存中的MeterRegistry.
切片测试中不支持导出数据@AutoConfigureMetrics注解。
使用追踪
无论你的类路径如何,报告数据的追踪组件在使用时都不会被自动配置@SpringBootTest.
如果你需要这些组件作为积分测试的一部分,请用@AutoConfigureTracing.
如果你创建了自己的报表组件(例如自定义的)SpanExporter或勇敢。控者。控者如果你不希望它们在测试中活跃,可以使用@ConditionalOnEnabledTracingExport注释以禁用它们。
如果你在切片测试中注释为@AutoConfigureTracing它会自动配置一个无作程序示 踪.
切片测试中不支持导出数据@AutoConfigureTracing注解。
嘲笑与间谍豆
在运行测试时,有时需要在应用上下文中模拟某些组件。 例如,你可能有一个远程服务的假象,在开发过程中无法使用。 模拟在模拟在真实环境中难以触发的故障时也很有用。
Spring Framework 包含@MockitoBean注释可用于定义 Mockito 模拟,指在你的应用上下文.
此外@MockitoSpyBean可以用来定义Mockito间谍。
想了解更多功能,请参见 Spring Framework 文档。
自动配置测试
Spring Boot 的自动配置系统对应用程序表现良好,但有时测试时会稍显繁琐。 通常只加载用于测试应用“切片”所需的配置部分。 例如,你可能想测试 Spring MVC 控制器是否正确映射 URL,但你不想在测试中涉及数据库调用;或者你可能想测试 JPA 实体,但测试时你不关注网页层。
结合时Spring-boot-test-autoconfigureSpring Boot 的测试模块包含许多注释,可用于自动配置此类“切片”。
它们各自的工作原理相似,提供@…测试加载应用上下文以及一个或多个@AutoConfigure......可用于自定义自动配置设置的注释。
每个切片限制组件扫描到合适的组件,并加载非常有限的自动配置类。
如果你需要排除其中一个,大多数@…测试注释提供exclusionAutoConfiguration属性。
或者,你可以使用@ImportAutoConfiguration#exclude. |
通过使用多个“切片”来包含多个“切片”@…测试不支持单一测试中的注释。
如果你需要多个“切片”,可以从以下几个@…测试注释和包括@AutoConfigure......其他“切片”的手写注释。 |
也可以使用@AutoConfigure......标准注释@SpringBootTest注解。
如果你不想“切片”你的应用,但又想用一些自动配置的测试豆,你可以用这个组合。 |
自动配置的JSON测试
为了测试对象的JSON序列化和反序列化是否正常工作,你可以使用@JsonTest注释来自Spring-boot-test-autoconfigure模块。@JsonTest自动配置可用的支持的JSON映射器,这些映射器可以是以下库之一:
-
Jackson
JsonMapper任何@JacksonComponent豆子和任何JacksonJackson模块 -
Jackson 2(已弃用)
对象映射器任何@JsonComponent豆子和任何Jackson模块 -
Gson -
Jsonb
如果你需要配置自动配置的元素,可以使用@AutoConfigureJsonTesters注解。
Spring Boot 包含基于 AssertJ 的辅助工具,可以配合 JSONAssert 和 JsonPath 库,检查 JSON 是否按预期出现。
这Jackson测试者,GsonTester,JsonbTester和BasicJsonTester类分别可用于 Jackson、Gson、Jsonb 和 Strings。
测试类中的任何辅助字段都可以是@Autowired使用@JsonTest.
以下示例展示了Jackson的一个测试类:
-
Java
-
Kotlin
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 {
@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");
}
}
import org.assertj.core.api.Assertions.assertThat
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
@JsonTest
class MyJsonTests(@Autowired val json: JacksonTester<VehicleDetails>) {
@Test
fun serialize() {
val details = VehicleDetails("Honda", "Civic")
// Assert against a `.json` file in the same package as the test
assertThat(json.write(details)).isEqualToJson("expected.json")
// Or use JSON path based assertions
assertThat(json.write(details)).hasJsonPathStringValue("@.make")
assertThat(json.write(details)).extractingJsonPathStringValue("@.make").isEqualTo("Honda")
}
@Test
fun deserialize() {
val content = "{\"make\":\"Ford\",\"model\":\"Focus\"}"
assertThat(json.parse(content)).isEqualTo(VehicleDetails("Ford", "Focus"))
assertThat(json.parseObject(content).make).isEqualTo("Ford")
}
}
JSON 辅助类也可以直接用于标准单元测试。
要做到这一点,请调用initFields助手的方法@BeforeEach如果你不使用方法,则@JsonTest. |
如果你用 Spring Boot 基于 AssertJ 的辅助工具在给定的 JSON 路径上对某个数字值进行断言,你可能无法使用isEqualTo这取决于类型。
相反,你可以使用 AssertJ满足断言该值符合给定条件。
例如,以下示例断言实际数是一个接近 的浮点值0.15在0.01.
-
Java
-
Kotlin
@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)));
}
@Test
fun someTest() {
val value = SomeObject(0.152f)
assertThat(json.write(value)).extractingJsonPathNumberValue("@.test.numberValue")
.satisfies(ThrowingConsumer { number ->
assertThat(number.toFloat()).isCloseTo(0.15f, within(0.01f))
})
}
自动配置的春季MVC测试
要测试 Spring MVC 控制器是否按预期工作,可以使用@WebMvcTest注释来自Spring-boot-webmvc-test模块。@WebMvcTest自动配置 Spring MVC 基础设施,并将扫描豆限制为@Controller,@ControllerAdvice,@JacksonComponent,@JsonComponent(已弃用),转炉,通用转换器,Filter,拦截者,WebMvcConfigurer,WebMvc注册和HandlerMethodArgumentResolver.
定期@Component和@ConfigurationProperties当@WebMvcTest使用注释。@EnableConfigurationProperties可以用来包括@ConfigurationProperties豆。
以下是启用的自动配置设置列表@WebMvcTest可在附录中找到。 |
经常@WebMvcTest限制在单个控制器上,并与以下设备结合使用@MockitoBean为所需的协作者提供模拟实现。
@WebMvcTest自动配置莫克麦克.
模拟MVC提供了一种强大的方法,可以快速测试MVC控制器,而无需启动完整的HTTP服务器。
如果 AssertJ 可用,AssertJ 支持将由以下提供MockMvcTester也是自动配置的。
你也可以自动配置莫克麦克和MockMvcTester在一个非——@WebMvcTest(例如:@SpringBootTest)通过注释@AutoConfigureMockMvc.
以下示例使用MockMvcTester: |
-
Java
-
Kotlin
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.test.web.servlet.assertj.MockMvcTester;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
@WebMvcTest(UserVehicleController.class)
class MyControllerTests {
@Autowired
private MockMvcTester mvc;
@MockitoBean
private UserVehicleService userVehicleService;
@Test
void testExample() {
given(this.userVehicleService.getVehicleDetails("sboot"))
.willReturn(new VehicleDetails("Honda", "Civic"));
assertThat(this.mvc.get().uri("/sboot/vehicle").accept(MediaType.TEXT_PLAIN))
.hasStatusOk()
.hasBodyTextEqualTo("Honda Civic");
}
}
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.mockito.BDDMockito.given
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest
import org.springframework.http.MediaType
import org.springframework.test.context.bean.override.mockito.MockitoBean
import org.springframework.test.web.servlet.assertj.MockMvcTester
@WebMvcTest(UserVehicleController::class)
class MyControllerTests(@Autowired val mvc: MockMvcTester) {
@MockitoBean
lateinit var userVehicleService: UserVehicleService
@Test
fun testExample() {
given(userVehicleService.getVehicleDetails("sboot"))
.willReturn(VehicleDetails("Honda", "Civic"))
assertThat(mvc.get().uri("/sboot/vehicle").accept(MediaType.TEXT_PLAIN))
.hasStatusOk().hasBodyTextEqualTo("Honda Civic")
}
}
如果你需要配置自动配置的元素(例如,何时需要应用servletFilter),你可以在@AutoConfigureMockMvc注解。 |
如果你使用 HtmlUnit 和 Selenium,自动配置还会提供一个 HtmlUnitWeb客户端豆子和/或硒WebDriver(网络驱动)豆。
以下示例使用 HtmlUnit:
-
Java
-
Kotlin
import org.htmlunit.WebClient;
import org.htmlunit.html.HtmlPage;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
@WebMvcTest(UserVehicleController.class)
class MyHtmlUnitTests {
@Autowired
private WebClient webClient;
@MockitoBean
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");
}
}
import org.assertj.core.api.Assertions.assertThat
import org.htmlunit.WebClient
import org.htmlunit.html.HtmlPage
import org.junit.jupiter.api.Test
import org.mockito.BDDMockito.given
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest
import org.springframework.test.context.bean.override.mockito.MockitoBean
@WebMvcTest(UserVehicleController::class)
class MyHtmlUnitTests(@Autowired val webClient: WebClient) {
@MockitoBean
lateinit var userVehicleService: UserVehicleService
@Test
fun testExample() {
given(userVehicleService.getVehicleDetails("sboot")).willReturn(VehicleDetails("Honda", "Civic"))
val page = webClient.getPage<HtmlPage>("/sboot/vehicle.html")
assertThat(page.body.textContent).isEqualTo("Honda Civic")
}
}
默认情况下,Spring Boot 会WebDriver(网络驱动)在一个特殊的“示范域”中,确保驱动程序在每次测试后退出,并注入一个新的实例。
如果你不想看到这种行为,可以添加@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)给你的WebDriver(网络驱动) @Bean定义。 |
这webDriverSpring Boot创建的scope将替换任何同名的用户自定义scope。
如果你定义了自己的webDriver你可能会发现它在使用时停止工作@WebMvcTest. |
如果你的职业路径上有Spring Security,@WebMvcTest也会扫描WebSecurityConfigurer豆。
你可以使用Spring Security的测试支持,而不是完全禁用这些测试的安全功能。
关于如何使用 Spring Security 的更多细节莫克麦克支持可以在这个“使用春季安全测试”“作指南”部分找到。
| 有时候,写春季MVC测试还不够;Spring Boot 可以帮助你在实际服务器上运行完整的端到端测试。 |
自动配置的 Spring WebFlux 测试
为了测试 Spring WebFlux 控制器是否正常工作,你可以使用@WebFluxTest注释来自春开网通量测试模块。@WebFluxTest自动配置 Spring WebFlux 基础设施,并将扫描豆限制为@Controller,@ControllerAdvice,@JacksonComponent,@JsonComponent(已弃用),转炉,通用转换器和WebFluxConfigurer.
定期@Component和@ConfigurationProperties当@WebFluxTest使用注释。@EnableConfigurationProperties可以用来包括@ConfigurationProperties豆。
以下为启用的自动配置列表@WebFluxTest可在附录中找到。 |
经常@WebFluxTest仅限于一个控制器,并与@MockitoBean注释以提供所需协作者的模拟实现。
@WebFluxTest自动配置WebTestClient,它提供了一种强大的方法,可以快速测试WebFlux控制器,而无需启动完整的HTTP服务器。
你也可以自动配置WebTestClient在一个非——@WebFluxTest(例如:@SpringBootTest)通过注释@AutoConfigureWebTestClient. |
以下示例展示了一个同时使用两者@WebFluxTest以及一个WebTestClient:
-
Java
-
Kotlin
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.webflux.test.autoconfigure.WebFluxTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.test.web.reactive.server.WebTestClient;
import static org.mockito.BDDMockito.given;
@WebFluxTest(UserVehicleController.class)
class MyControllerTests {
@Autowired
private WebTestClient webClient;
@MockitoBean
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");
}
}
import org.junit.jupiter.api.Test
import org.mockito.BDDMockito.given
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.webflux.test.autoconfigure.WebFluxTest
import org.springframework.http.MediaType
import org.springframework.test.context.bean.override.mockito.MockitoBean
import org.springframework.test.web.reactive.server.WebTestClient
import org.springframework.test.web.reactive.server.expectBody
@WebFluxTest(UserVehicleController::class)
class MyControllerTests(@Autowired val webClient: WebTestClient) {
@MockitoBean
lateinit var userVehicleService: UserVehicleService
@Test
fun testExample() {
given(userVehicleService.getVehicleDetails("sboot"))
.willReturn(VehicleDetails("Honda", "Civic"))
webClient.get().uri("/sboot/vehicle").accept(MediaType.TEXT_PLAIN).exchange()
.expectStatus().isOk
.expectBody<String>().isEqualTo("Honda Civic")
}
}
该设置仅由 WebFlux 应用程序支持WebTestClient目前,在模拟网页应用中只与WebFlux兼容。 |
@WebFluxTest无法检测通过功能性Web框架注册的路由。
用于测试路由器功能在上下文中,考虑导入你的路由器功能你自己用@Import或者通过使用@SpringBootTest. |
@WebFluxTest无法检测到注册为@Bean类型安全网滤网链.
要把这个功能包含在测试中,你需要导入注册豆子的配置,方法是@Import或者通过使用@SpringBootTest. |
| 有时候,仅仅编写春季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 configuration
testImplementation("org.springframework.boot:spring-boot-starter-webflux")
}
该测试模块附带 GraphQlTester。
测试仪在考试中使用频率很高,所以一定要熟悉它的使用。
有GraphQLTester变体和Spring Boot会根据测试类型自动配置:
-
这
ExecutionGraphQlServiceTester在服务器端进行测试,无需客户端或传输 -
这
HttpGraphQLTester通过客户端连接到服务器进行测试,客户端连接服务器,无论是否配备实时服务器
Spring Boot 帮助你用@GraphQlTest注释来自spring-boot-graphql-test模块。@GraphQlTest自动配置 Spring GraphQL 基础设施,无需任何传输或服务器。
这限制了扫描豆子的范围@Controller,RuntimeWiringConfigurer,Jackson分量,@JsonComponent(已弃用),转炉,通用转换器,DataFetcherExceptionResolver,仪表和GraphQLSourceBuilder定制器.
定期@Component和@ConfigurationProperties当@GraphQlTest使用注释。@EnableConfigurationProperties可以用来包括@ConfigurationProperties豆。
以下为启用的自动配置列表@GraphQlTest可在附录中找到。 |
经常@GraphQlTest仅限于一组控制器,并与@MockitoBean注释以提供所需协作者的模拟实现。
-
Java
-
Kotlin
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.graphql.test.autoconfigure.GraphQlTest;
import org.springframework.graphql.test.tester.GraphQlTester;
@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!");
}
}
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.graphql.test.autoconfigure.GraphQlTest
import org.springframework.graphql.test.tester.GraphQlTester
@GraphQlTest(GreetingController::class)
internal class GreetingControllerTests {
@Autowired
lateinit var graphQlTester: GraphQlTester
@Test
fun shouldGreetWithSpecificName() {
graphQlTester.document("{ greeting(name: \"Alice\") } ").execute().path("greeting").entity(String::class.java)
.isEqualTo("Hello, Alice!")
}
@Test
fun shouldGreetWithDefaultName() {
graphQlTester.document("{ greeting } ").execute().path("greeting").entity(String::class.java)
.isEqualTo("Hello, Spring!")
}
}
@SpringBootTest测试是完整的集成测试,涉及整个应用程序。
一个HttpGraphQLTester可以通过注释你的测试类来添加 bean@AutoConfigureHttpGraphQlTester来自spring-boot-graphql-test模块:
-
Java
-
Kotlin
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.graphql.test.autoconfigure.tester.AutoConfigureHttpGraphQlTester;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.graphql.test.tester.HttpGraphQlTester;
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureHttpGraphQlTester
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!");
}
}
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.graphql.test.autoconfigure.tester.AutoConfigureHttpGraphQlTester
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment
import org.springframework.graphql.test.tester.HttpGraphQlTester
import org.springframework.http.HttpHeaders
import org.springframework.test.web.reactive.server.WebTestClient
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureHttpGraphQlTester
class GraphQlIntegrationTests {
@Test
fun shouldGreetWithSpecificName(@Autowired graphQlTester: HttpGraphQlTester) {
val authenticatedTester = graphQlTester.mutate()
.webTestClient { client: WebTestClient.Builder ->
client.defaultHeaders { headers: HttpHeaders ->
headers.setBasicAuth("admin", "ilovespring")
}
}.build()
authenticatedTester.document("{ greeting(name: \"Alice\") } ").execute()
.path("greeting").entity(String::class.java).isEqualTo("Hello, Alice!")
}
}
这HttpGraphQLTesterBean 使用积分测试的相关传输。
使用随机或定义端口时,测试器会针对在线服务器进行配置。
将测试器绑定为莫克麦克记得在你的测试类上注释:@AutoConfigureMockMvc.
自动配置数据Cassandra测试
你可以使用@DataCassandraTest来自spring-boot-data-cassandra-test用于测试Data Cassandra应用的模块。
默认情况下,它配置为卡桑德拉模板,扫描@Table并配置 Spring Data Cassandra 仓库。
定期@Component和@ConfigurationProperties当@DataCassandraTest使用注释。@EnableConfigurationProperties可以用来包括@ConfigurationProperties豆。
(关于如何搭配Spring靴使用卡桑德拉,请参见卡桑德拉。)
以下是启用的自动配置设置列表@DataCassandraTest可在附录中找到。 |
以下示例展示了在 Spring Boot 中使用 Cassandra 测试的典型设置:
-
Java
-
Kotlin
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.data.cassandra.test.autoconfigure.DataCassandraTest;
@DataCassandraTest
class MyDataCassandraTests {
@Autowired
private SomeRepository repository;
}
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.data.cassandra.test.autoconfigure.DataCassandraTest
@DataCassandraTest
class MyDataCassandraTests(@Autowired val repository: SomeRepository)
自动配置数据 Couchbase 测试
你可以使用@DataCouchbaseTest来自Spring-boot-data-Couchbase-test用于测试Data Couchbase应用的模块。
默认情况下,它配置为沙发底座模板或ReactiveCouchbaseTemplate,扫描@Document并配置 Spring Data Couchbase 仓库。
定期@Component和@ConfigurationProperties当@DataCouchbaseTest使用注释。@EnableConfigurationProperties可以用来包括@ConfigurationProperties豆。
(关于使用 Couchbase 配合 Spring Boot 的更多信息,请参见本章前半部分的 Couchbase。)
以下是启用的自动配置设置列表@DataCouchbaseTest可在附录中找到。 |
以下示例展示了在 Spring Boot 中使用 Couchbase 测试的典型设置:
-
Java
-
Kotlin
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.data.couchbase.test.autoconfigure.DataCouchbaseTest;
@DataCouchbaseTest
class MyDataCouchbaseTests {
@Autowired
private SomeRepository repository;
// ...
}
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.data.couchbase.test.autoconfigure.DataCouchbaseTest
@DataCouchbaseTest
class MyDataCouchbaseTests(@Autowired val repository: SomeRepository) {
// ...
}
自动配置的数据弹性搜索测试
你可以使用@DataElasticsearchTest来自spring-boot-data-elasticsearch-test用于测试数据弹性搜索应用的模块。
默认情况下,它配置为弹性搜索模板,扫描@Document并配置 Spring Data Elasticsearch 仓库。
定期@Component和@ConfigurationProperties当@DataElasticsearchTest使用注释。@EnableConfigurationProperties可以用来包括@ConfigurationProperties豆。
(关于如何与 Spring Boot 结合 Elasticsearch 了解更多,请参见本章前半部分的 Elasticsearch。)
以下是启用的自动配置设置列表@DataElasticsearchTest可在附录中找到。 |
以下示例展示了在 Spring Boot 中使用 Elasticsearch 测试的典型设置:
-
Java
-
Kotlin
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.data.elasticsearch.test.autoconfigure.DataElasticsearchTest;
@DataElasticsearchTest
class MyDataElasticsearchTests {
@Autowired
private SomeRepository repository;
// ...
}
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.data.elasticsearch.test.autoconfigure.DataElasticsearchTest
@DataElasticsearchTest
class MyDataElasticsearchTests(@Autowired val repository: SomeRepository) {
// ...
}
自动配置数据JPA测试
你可以使用@DataJpaTest注释来自Spring-boot-data-jpa-test用于测试数据JPA应用的模块。
默认情况下,它扫描的是@Entity分类并配置 Spring Data JPA 仓库。
如果类路径上有嵌入式数据库,它也会配置一个。
SQL 查询默认通过设置spring.jpa.show-sql属性到true.
这可以通过以下方式禁用showSQL注释的属性。
定期@Component和@ConfigurationProperties当@DataJpaTest使用注释。@EnableConfigurationProperties可以用来包括@ConfigurationProperties豆。
以下是启用的自动配置设置列表@DataJpaTest可在附录中找到。 |
默认情况下,数据JPA测试是事务型的,每次测试结束时都会回滚。 详情请参见春季框架参考文档中的相关部分。 如果这不是你想要的,你可以在测试或整个类中禁用事务管理,具体如下:
-
Java
-
Kotlin
import org.springframework.boot.data.jpa.test.autoconfigure.DataJpaTest;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@DataJpaTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
class MyNonTransactionalTests {
// ...
}
import org.springframework.boot.data.jpa.test.autoconfigure.DataJpaTest
import org.springframework.transaction.annotation.Propagation
import org.springframework.transaction.annotation.Transactional
@DataJpaTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
class MyNonTransactionalTests {
// ...
}
数据JPA测试也可以注入TestEntityManagerBEAN,提供了标准JPA的替代方案实体管理器那是专门为测试设计的。
TestEntityManager也可以通过添加@AutoConfigureTestEntityManager.
在这样做时,确保你的测试正在事务中运行,例如通过添加@Transactional在你的测试类别或方法上。 |
一个Jdbc模板如果你需要,也可以提供。
以下示例展示了@DataJpaTest注释使用情况:
-
Java
-
Kotlin
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.data.jpa.test.autoconfigure.DataJpaTest;
import org.springframework.boot.jpa.test.autoconfigure.TestEntityManager;
import static org.assertj.core.api.Assertions.assertThat;
@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");
}
}
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.data.jpa.test.autoconfigure.DataJpaTest
import org.springframework.boot.jpa.test.autoconfigure.TestEntityManager
@DataJpaTest
class MyRepositoryTests(@Autowired val entityManager: TestEntityManager, @Autowired val repository: UserRepository) {
@Test
fun testExample() {
entityManager.persist(User("sboot", "1234"))
val user = repository.findByUsername("sboot")
assertThat(user?.username).isEqualTo("sboot")
assertThat(user?.employeeNumber).isEqualTo("1234")
}
}
内存内嵌入式数据库通常适合测试,因为它们速度快且无需安装。
不过,如果你更喜欢对真实数据库进行测试,可以使用@AutoConfigureTestDatabase注释,如下示例所示:
-
Java
-
Kotlin
import org.springframework.boot.data.jpa.test.autoconfigure.DataJpaTest;
import org.springframework.boot.jdbc.test.autoconfigure.AutoConfigureTestDatabase;
import org.springframework.boot.jdbc.test.autoconfigure.AutoConfigureTestDatabase.Replace;
@DataJpaTest
@AutoConfigureTestDatabase(replace = Replace.NONE)
class MyRepositoryTests {
// ...
}
import org.springframework.boot.jdbc.test.autoconfigure.AutoConfigureTestDatabase
import org.springframework.boot.data.jpa.test.autoconfigure.DataJpaTest
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class MyRepositoryTests {
// ...
}
自动配置的JDBC测试
@JdbcTest来自spring-boot-jdbc-test模类似于@DataJdbcTest但对于只需 a 的检验 是数据来源并且不要使用Spring Data JDBC。
默认情况下,它配置内存内嵌入式数据库和Jdbc模板.
定期@Component和@ConfigurationProperties当@JdbcTest使用注释。@EnableConfigurationProperties可以用来包括@ConfigurationProperties豆。
默认情况下,JDBC测试是事务型的,每次测试结束时都会回滚。 详情请参见春季框架参考文档中的相关部分。 如果这不是你想要的,你可以禁用测试或整个类的事务管理,具体如下:
-
Java
-
Kotlin
import org.springframework.boot.jdbc.test.autoconfigure.JdbcTest;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@JdbcTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
class MyTransactionalTests {
}
import org.springframework.boot.jdbc.test.autoconfigure.JdbcTest
import org.springframework.transaction.annotation.Propagation
import org.springframework.transaction.annotation.Transactional
@JdbcTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
class MyTransactionalTests
如果你更喜欢测试对应真实数据库,可以使用@AutoConfigureTestDatabase注释方式与@DataJpaTest.
(参见自动配置的数据JPA测试。)
自动配置数据JDBC测试
@DataJdbcTest来自Spring-boot-Data-JDBC-Test模类似于@JdbcTest但适用于使用 Spring Data JDBC 仓库的测试。
默认情况下,它配置内存内嵌入式数据库,即Jdbc模板以及Spring Data JDBC仓库。
只摘要Jdbc配置当@DataJdbcTest使用了常规注释@Component和@ConfigurationProperties豆子不会被扫描。@EnableConfigurationProperties可以用来包括@ConfigurationProperties豆。
以下为启用的自动配置列表@DataJdbcTest可在附录中找到。 |
如果你更喜欢测试对应真实数据库,可以使用@AutoConfigureTestDatabase注释方式与@DataJpaTest.
(参见自动配置的数据JPA测试。)
自动配置数据R2DBC测试
@DataR2dbcTest来自Spring-boot-data-r2dbc-test模类似于@DataJdbcTest但适用于使用 Spring Data R2DBC 仓库的测试。
默认情况下,它配置内存内嵌入式数据库,以及R2dbcEntityTemplate以及Spring Data R2DBC仓库。
定期@Component和@ConfigurationProperties当@DataR2dbcTest使用注释。@EnableConfigurationProperties可以用来包括@ConfigurationProperties豆。
以下为启用的自动配置列表@DataR2dbcTest可在附录中找到。 |
默认情况下,Data R2DBC 测试不是事务性的。
如果你更喜欢测试对应真实数据库,可以使用@AutoConfigureTestDatabase注释方式与@DataJpaTest.
(参见自动配置的数据JPA测试。)
自动配置的jOOQ测试
你可以使用@JooqTest从spring-boot-jooq-test方式类似于@JdbcTest但对于与jOOQ相关的测试,
由于 jOOQ 高度依赖基于 Java 的模式,该模式与现有的数据库模式对应,因此数据来源被使用。
如果你想用内存数据库替代它,可以用@AutoConfigureTestDatabase来覆盖那些设置。
(关于如何使用 jOOQ 配合 Spring Boot 的更多信息,请参见使用 jOOQ。)
定期@Component和@ConfigurationProperties当@JooqTest使用注释。@EnableConfigurationProperties可以用来包括@ConfigurationProperties豆。
@JooqTest配置 aDSLContext.
以下示例展示了@JooqTest注释使用情况:
-
Java
-
Kotlin
import org.jooq.DSLContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.jooq.test.autoconfigure.JooqTest;
@JooqTest
class MyJooqTests {
@Autowired
private DSLContext dslContext;
// ...
}
import org.jooq.DSLContext
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.jooq.test.autoconfigure.JooqTest
@JooqTest
class MyJooqTests(@Autowired val dslContext: DSLContext) {
// ...
}
JOOQ 测试是事务型的,默认在每次测试结束时回滚。 如果你不想要这样,可以像JDBC示例中那样禁用测试或整个测试类的事务管理。
自动配置数据 MongoDB 测试
你可以使用@DataMongoTest来自Spring-boot-data-mongodb-test用于测试MongoDB应用的模块。
默认情况下,它配置为Mongo模板,扫描@Document并配置 Spring Data MongoDB 仓库。
定期@Component和@ConfigurationProperties当@DataMongoTest使用注释。@EnableConfigurationProperties可以用来包括@ConfigurationProperties豆。
(关于使用 MongoDB 配合 Spring Boot 的更多信息,请参见 MongoDB。)
以下是启用的自动配置设置列表@DataMongoTest可在附录中找到。 |
以下类别显示@DataMongoTest注释使用情况:
-
Java
-
Kotlin
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.data.mongodb.test.autoconfigure.DataMongoTest;
import org.springframework.data.mongodb.core.MongoTemplate;
@DataMongoTest
class MyDataMongoDbTests {
@Autowired
private MongoTemplate mongoTemplate;
// ...
}
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.data.mongodb.test.autoconfigure.DataMongoTest
import org.springframework.data.mongodb.core.MongoTemplate
@DataMongoTest
class MyDataMongoDbTests(@Autowired val mongoTemplate: MongoTemplate) {
// ...
}
自动配置数据 Neo4j 测试
你可以使用@DataNeo4jTest来自Spring-boot-data-neo4j-test用于测试 Neo4j 应用的模块。
默认情况下,它扫描的是@Node并配置 Spring Data Neo4j 仓库。
定期@Component和@ConfigurationProperties当@DataNeo4jTest使用注释。@EnableConfigurationProperties可以用来包括@ConfigurationProperties豆。
(关于如何与Spring Boot一起使用Neo4J,请参见Neo4j。)
以下是启用的自动配置设置列表@DataNeo4jTest可在附录中找到。 |
以下示例展示了在 Spring Boot 中使用 Neo4J 测试的典型设置:
-
Java
-
Kotlin
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.data.neo4j.test.autoconfigure.DataNeo4jTest;
@DataNeo4jTest
class MyDataNeo4jTests {
@Autowired
private SomeRepository repository;
// ...
}
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.data.neo4j.test.autoconfigure.DataNeo4jTest
@DataNeo4jTest
class MyDataNeo4jTests(@Autowired val repository: SomeRepository) {
// ...
}
默认情况下,Data Neo4j 测试是事务性的,每次测试结束时会回滚。 详情请参见春季框架参考文档中的相关部分。 如果这不是你想要的,你可以禁用测试或整个类的事务管理,具体如下:
-
Java
-
Kotlin
import org.springframework.boot.data.neo4j.test.autoconfigure.DataNeo4jTest;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@DataNeo4jTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
class MyDataNeo4jTests {
}
import org.springframework.boot.data.neo4j.test.autoconfigure.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来自Spring-boot-data-redis-test用于测试Data Redis应用的模块。
默认情况下,它扫描的是@RedisHash类并配置 Spring Data Redis 仓库。
定期@Component和@ConfigurationProperties当@DataRedisTest使用注释。@EnableConfigurationProperties可以用来包括@ConfigurationProperties豆。
(关于如何使用 Redis 配合 Spring Boot,请参见 Redis。)
以下是启用的自动配置设置列表@DataRedisTest可在附录中找到。 |
以下示例展示了@DataRedisTest注释使用情况:
-
Java
-
Kotlin
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.data.redis.test.autoconfigure.DataRedisTest;
@DataRedisTest
class MyDataRedisTests {
@Autowired
private SomeRepository repository;
// ...
}
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.data.redis.test.autoconfigure.DataRedisTest
@DataRedisTest
class MyDataRedisTests(@Autowired val repository: SomeRepository) {
// ...
}
自动配置数据LDAP测试
你可以使用@DataLdapTest用于测试数据LDAP应用。
默认情况下,它配置内存内嵌的 LDAP(如果有的话),配置LdapTemplate,扫描@Entry并配置 Spring Data LDAP 仓库。
定期@Component和@ConfigurationProperties当@DataLdapTest使用注释。@EnableConfigurationProperties可以用来包括@ConfigurationProperties豆。
(有关使用 LDAP 与 Spring Boot 的更多内容,请参见 LDAP。)
以下是启用的自动配置设置列表@DataLdapTest可在附录中找到。 |
以下示例展示了@DataLdapTest注释使用情况:
-
Java
-
Kotlin
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.data.ldap.test.autoconfigure.DataLdapTest;
import org.springframework.ldap.core.LdapTemplate;
@DataLdapTest
class MyDataLdapTests {
@Autowired
private LdapTemplate ldapTemplate;
// ...
}
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.data.ldap.test.autoconfigure.DataLdapTest
import org.springframework.ldap.core.LdapTemplate
@DataLdapTest
class MyDataLdapTests(@Autowired val ldapTemplate: LdapTemplate) {
// ...
}
内存内嵌入式 LDAP 通常适合测试,因为它速度快且无需开发者安装。 然而,如果你更愿意在真实的LDAP服务器上运行测试,应排除嵌入的LDAP自动配置,如下例所示:
-
Java
-
Kotlin
import org.springframework.boot.data.ldap.test.autoconfigure.DataLdapTest;
import org.springframework.boot.ldap.autoconfigure.embedded.EmbeddedLdapAutoConfiguration;
@DataLdapTest(excludeAutoConfiguration = EmbeddedLdapAutoConfiguration.class)
class MyDataLdapTests {
// ...
}
import org.springframework.boot.ldap.autoconfigure.embedded.EmbeddedLdapAutoConfiguration
import org.springframework.boot.data.ldap.test.autoconfigure.DataLdapTest
@DataLdapTest(excludeAutoConfiguration = [EmbeddedLdapAutoConfiguration::class])
class MyDataLdapTests {
// ...
}
自动配置的 REST 客户端
你可以使用@RestClientTest注释来自Spring-靴-托客户端-测试用于测试 REST 客户端的模块。
默认情况下,它会自动配置Jackson、GSON和Jsonb支持,配置一个Rest模板构建器以及一个RestClient.Builder,并增加了支持MockRestServiceServer.
定期@Component和@ConfigurationProperties当@RestClientTest使用注释。@EnableConfigurationProperties可以用来包括@ConfigurationProperties豆。
以下是启用的自动配置设置列表@RestClientTest可在附录中找到。 |
你想测试的具体豆子应通过以下方式指定值或组件属性@RestClientTest.
当使用Rest模板构建器在被测试的豆子中 和RestTemplateBuilder.rootUri(String rootUri)在构建Rest模板,则应从中省略根URI。MockRestServiceServer期望如下示例所示:
-
Java
-
Kotlin
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.restclient.test.autoconfigure.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(org.springframework.boot.docs.testing.springbootapplications.autoconfiguredrestclient.RemoteVehicleDetailsService.class)
class MyRestTemplateServiceTests {
@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");
}
}
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.restclient.test.autoconfigure.RestClientTest
import org.springframework.http.MediaType
import org.springframework.test.web.client.MockRestServiceServer
import org.springframework.test.web.client.match.MockRestRequestMatchers
import org.springframework.test.web.client.response.MockRestResponseCreators
@RestClientTest(RemoteVehicleDetailsService::class)
class MyRestTemplateServiceTests(
@Autowired val service: RemoteVehicleDetailsService,
@Autowired val server: MockRestServiceServer) {
@Test
fun getVehicleDetailsWhenResultIsSuccessShouldReturnDetails() {
server.expect(MockRestRequestMatchers.requestTo("/greet/details"))
.andRespond(MockRestResponseCreators.withSuccess("hello", MediaType.TEXT_PLAIN))
val greeting = service.callRestService()
assertThat(greeting).isEqualTo("hello")
}
}
当使用RestClient.Builder在被测试的豆子中,或使用A时Rest模板构建器没有呼唤rootUri(字符串 rootURI),必须在MockRestServiceServer期望如下示例所示:
-
Java
-
Kotlin
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.restclient.test.autoconfigure.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 {
@Autowired
private RemoteVehicleDetailsService service;
@Autowired
private MockRestServiceServer server;
@Test
void 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");
}
}
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.restclient.test.autoconfigure.RestClientTest
import org.springframework.http.MediaType
import org.springframework.test.web.client.MockRestServiceServer
import org.springframework.test.web.client.match.MockRestRequestMatchers
import org.springframework.test.web.client.response.MockRestResponseCreators
@RestClientTest(RemoteVehicleDetailsService::class)
class MyRestClientServiceTests(
@Autowired val service: RemoteVehicleDetailsService,
@Autowired val server: MockRestServiceServer) {
@Test
fun getVehicleDetailsWhenResultIsSuccessShouldReturnDetails() {
server.expect(MockRestRequestMatchers.requestTo("https://example.com/greet/details"))
.andRespond(MockRestResponseCreators.withSuccess("hello", MediaType.TEXT_PLAIN))
val greeting = service.callRestService()
assertThat(greeting).isEqualTo("hello")
}
}
自动配置的网页客户端
你可以使用@WebClientTest注释来自Spring-boot-webclient-test模块用于测试代码,使用Web客户端.
默认情况下,它会自动配置 Jackson、GSON 和 Jsonb 支持,并配置WebClient.Builder.
定期@Component和@ConfigurationProperties当@WebClientTest使用注释。@EnableConfigurationProperties可以用来包括@ConfigurationProperties豆。
以下是启用的自动配置设置列表@WebClientTest可在附录中找到。 |
你想测试的具体豆子应通过以下方式指定值或组件属性@WebClientTest.
自动配置 Spring REST Docs 测试
你可以使用@AutoConfigureRestDocs来自“Spring-boot-restdocs- 模块”的注释,用于在与 Mock MVC 或 WebTestClient 的测试中使用 Spring REST 文档。
它消除了 Spring REST 文档中对 JUnit 扩展的需求。
@AutoConfigureRestDocs可以用来覆盖默认输出目录(目标/生成片段如果你用的是Maven或者构建/生成片段如果你用的是Gradle)。
它还可用于配置任何文档中出现的主机、方案和端口。
自动配置 Spring REST 文档测试,使用模拟 MVC
@AutoConfigureRestDocs自定义莫克麦克在测试基于 servlet 的 web 应用时使用 Spring REST 文档。
你可以用以下方式注射@Autowired并像使用模拟 MVC 和 Spring REST 文档时那样在测试中使用它,如下示例所示:
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.restdocs.test.autoconfigure.AutoConfigureRestDocs;
import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.assertj.MockMvcTester;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
@WebMvcTest(UserController.class)
@AutoConfigureRestDocs
class MyUserDocumentationTests {
@Autowired
private MockMvcTester mvc;
@Test
void listUsers() {
assertThat(this.mvc.get().uri("/users").accept(MediaType.TEXT_PLAIN)).hasStatusOk()
.apply(document("list-users"));
}
}
如果你更喜欢使用 AssertJ 积分,MockMvcTester也可用,如下示例所示:
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.restdocs.test.autoconfigure.AutoConfigureRestDocs;
import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.assertj.MockMvcTester;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
@WebMvcTest(UserController.class)
@AutoConfigureRestDocs
class MyUserDocumentationTests {
@Autowired
private MockMvcTester mvc;
@Test
void listUsers() {
assertThat(this.mvc.get().uri("/users").accept(MediaType.TEXT_PLAIN)).hasStatusOk()
.apply(document("list-users"));
}
}
两者重复使用相同的内容莫克麦克实例在幕后作,所以任何配置都适用于两者。
如果你需要比 Spring REST Docs 配置更多的控制,属性@AutoConfigureRestDocs,你可以用RestDocsMockMvcConfigurationCustomizer豆子,如下例所示:
-
Java
-
Kotlin
import org.springframework.boot.restdocs.test.autoconfigure.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 {
@Override
public void customize(MockMvcRestDocumentationConfigurer configurer) {
configurer.snippets().withTemplateFormat(TemplateFormats.markdown());
}
}
import org.springframework.boot.restdocs.test.autoconfigure.RestDocsMockMvcConfigurationCustomizer
import org.springframework.boot.test.context.TestConfiguration
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentationConfigurer
import org.springframework.restdocs.templates.TemplateFormats
@TestConfiguration(proxyBeanMethods = false)
class MyRestDocsConfiguration : RestDocsMockMvcConfigurationCustomizer {
override fun customize(configurer: MockMvcRestDocumentationConfigurer) {
configurer.snippets().withTemplateFormat(TemplateFormats.markdown())
}
}
如果你想利用 Spring REST Docs 对参数化输出目录的支持,可以创建一个RestDocumentationResultHandler豆。
自动配置调用总是做通过该结果处理,从而导致莫克麦克调用自动生成默认片段。
以下示例展示了一个RestDocumentationResultHandler定义:
-
Java
-
Kotlin
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 {
@Bean
public RestDocumentationResultHandler restDocumentation() {
return MockMvcRestDocumentation.document("{method-name}");
}
}
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)
class MyResultHandlerConfiguration {
@Bean
fun restDocumentation(): RestDocumentationResultHandler {
return MockMvcRestDocumentation.document("{method-name}")
}
}
自动配置 Spring REST Docs 测试 with WebTestClient
@AutoConfigureRestDocs也可以与WebTestClient在测试响应式网页应用时。
你可以用以下方式注射@Autowired并且像平时使用时一样在测试中使用它@WebFluxTest以及 Spring REST 文档,如下示例所示:
-
Java
-
Kotlin
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.restdocs.test.autoconfigure.AutoConfigureRestDocs;
import org.springframework.boot.webflux.test.autoconfigure.WebFluxTest;
import org.springframework.test.web.reactive.server.WebTestClient;
import static org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation.document;
@WebFluxTest
@AutoConfigureRestDocs
class MyUsersDocumentationTests {
@Autowired
private WebTestClient webTestClient;
@Test
void listUsers() {
this.webTestClient
.get().uri("/")
.exchange()
.expectStatus()
.isOk()
.expectBody()
.consumeWith(document("list-users"));
}
}
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.restdocs.test.autoconfigure.AutoConfigureRestDocs
import org.springframework.boot.webflux.test.autoconfigure.WebFluxTest
import org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation
import org.springframework.test.web.reactive.server.WebTestClient
@WebFluxTest
@AutoConfigureRestDocs
class MyUsersDocumentationTests(@Autowired val webTestClient: WebTestClient) {
@Test
fun listUsers() {
webTestClient
.get().uri("/")
.exchange()
.expectStatus()
.isOk
.expectBody()
.consumeWith(WebTestClientRestDocumentation.document("list-users"))
}
}
如果你需要比 Spring REST Docs 配置更多的控制,属性@AutoConfigureRestDocs,你可以用RestDocsWebTestClientConfigurationCustomizer豆子,如下例所示:
-
Java
-
Kotlin
import org.springframework.boot.restdocs.test.autoconfigure.RestDocsWebTestClientConfigurationCustomizer;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.restdocs.webtestclient.WebTestClientRestDocumentationConfigurer;
@TestConfiguration(proxyBeanMethods = false)
public class MyRestDocsConfiguration implements RestDocsWebTestClientConfigurationCustomizer {
@Override
public void customize(WebTestClientRestDocumentationConfigurer configurer) {
configurer.snippets().withEncoding("UTF-8");
}
}
import org.springframework.boot.restdocs.test.autoconfigure.RestDocsWebTestClientConfigurationCustomizer
import org.springframework.boot.test.context.TestConfiguration
import org.springframework.restdocs.webtestclient.WebTestClientRestDocumentationConfigurer
@TestConfiguration(proxyBeanMethods = false)
class MyRestDocsConfiguration : RestDocsWebTestClientConfigurationCustomizer {
override fun customize(configurer: WebTestClientRestDocumentationConfigurer) {
configurer.snippets().withEncoding("UTF-8")
}
}
如果你想利用 Spring REST Docs 对参数化输出目录的支持,可以使用WebTestClientBuilderCustomizer为每个实体交换结果配置一个消费者。
以下示例展示了这样的WebTestClientBuilderCustomizer定义:
-
Java
-
Kotlin
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.webtestclient.autoconfigure.WebTestClientBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import static org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation.document;
@TestConfiguration(proxyBeanMethods = false)
public class MyWebTestClientBuilderCustomizerConfiguration {
@Bean
public WebTestClientBuilderCustomizer restDocumentation() {
return (builder) -> builder.entityExchangeResultConsumer(document("{method-name}"));
}
}
import org.springframework.boot.test.context.TestConfiguration
import org.springframework.boot.webtestclient.autoconfigure.WebTestClientBuilderCustomizer
import org.springframework.context.annotation.Bean
import org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation
import org.springframework.test.web.reactive.server.WebTestClient
@TestConfiguration(proxyBeanMethods = false)
class MyWebTestClientBuilderCustomizerConfiguration {
@Bean
fun restDocumentation(): WebTestClientBuilderCustomizer {
return WebTestClientBuilderCustomizer { builder: WebTestClient.Builder ->
builder.entityExchangeResultConsumer(
WebTestClientRestDocumentation.document("{method-name}")
)
}
}
}
自动配置的 Spring Web 服务测试
自动配置的 Spring Web Services 客户端测试
你可以使用@WebServiceClientTest来自Spring-boot-webservices-test用于测试使用 Spring Web Services 项目调用 Web 服务的应用程序。
默认情况下,它配置为MockWebServiceServer豆子并自动定制你的WebService模板构建器.
(关于使用 Spring Boot 使用 Web Services 的更多信息,请参见 Web Services。)
以下是启用的自动配置设置列表@WebServiceClientTest可在附录中找到。 |
以下示例展示了@WebServiceClientTest注释使用情况:
-
Java
-
Kotlin
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.webservices.test.autoconfigure.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 {
@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);
}
}
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.webservices.test.autoconfigure.client.WebServiceClientTest
import org.springframework.ws.test.client.MockWebServiceServer
import org.springframework.ws.test.client.RequestMatchers
import org.springframework.ws.test.client.ResponseCreators
import org.springframework.xml.transform.StringSource
@WebServiceClientTest(SomeWebService::class)
class MyWebServiceClientTests(
@Autowired val server: MockWebServiceServer, @Autowired val someWebService: SomeWebService) {
@Test
fun mockServerCall() {
server
.expect(RequestMatchers.payload(StringSource("<request/>")))
.andRespond(ResponseCreators.withPayload(StringSource("<response><status>200</status></response>")))
assertThat(this.someWebService.test()).extracting(Response::status).isEqualTo(200)
}
}
自动配置的Spring Web Services Server测试
你可以使用@WebServiceServerTest来自Spring-boot-webservices-test用于测试使用 Spring Web Services 项目实现 Web 服务的应用程序的模块。
默认情况下,它配置为MockWebServiceClient可以用来调用你的 Web 服务端点。
(关于使用 Spring Boot 使用 Web Services 的更多信息,请参见 Web Services。)
以下是启用的自动配置设置列表@WebServiceServerTest可在附录中找到。 |
以下示例展示了@WebServiceServerTest注释使用情况:
-
Java
-
Kotlin
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.webservices.test.autoconfigure.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 {
@Autowired
private MockWebServiceClient client;
@Test
void mockServerCall() {
this.client
.sendRequest(RequestCreators.withPayload(new StringSource("<ExampleRequest/>")))
.andExpect(ResponseMatchers.payload(new StringSource("<ExampleResponse>42</ExampleResponse>")));
}
}
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.webservices.test.autoconfigure.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(@Autowired val client: MockWebServiceClient) {
@Test
fun mockServerCall() {
client
.sendRequest(RequestCreators.withPayload(StringSource("<ExampleRequest/>")))
.andExpect(ResponseMatchers.payload(StringSource("<ExampleResponse>42</ExampleResponse>")))
}
}
额外的自动配置与切片
每个片提供一个或多个@AutoConfigure......注释主要定义了应作为切片一部分包含的自动配置。
通过创建自定义方案,可以根据测试添加额外的自动配置@AutoConfigure......注释或通过添加@ImportAutoConfiguration如下例所示,测试结果如下:
-
Java
-
Kotlin
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.integration.autoconfigure.IntegrationAutoConfiguration;
import org.springframework.boot.jdbc.test.autoconfigure.JdbcTest;
@JdbcTest
@ImportAutoConfiguration(IntegrationAutoConfiguration.class)
class MyJdbcTests {
}
import org.springframework.boot.autoconfigure.ImportAutoConfiguration
import org.springframework.boot.integration.autoconfigure.IntegrationAutoConfiguration
import org.springframework.boot.jdbc.test.autoconfigure.JdbcTest
@JdbcTest
@ImportAutoConfiguration(IntegrationAutoConfiguration::class)
class MyJdbcTests
一定要不要用普通的@Import注释以导入自动配置,因为 Spring Boot 以特定方式处理。 |
或者,可以通过在存储于 的文件中注册片注释,添加额外的自动配置以支持片注释的任何用途元步枪/Spring如下例所示:
com.example.IntegrationAutoConfiguration
在这个例子中,com.example.集成自动配置在每个标注为 的测试上都启用@JdbcTest.
你可以在这个文件中使用注释。# |
切片或@AutoConfigure......只要注释通过元注释进行,就可以以@ImportAutoConfiguration. |
用户配置与切片
如果你以合理的方式构建代码,你的@SpringBootApplication类默认是测试的配置。
因此,重要的是不要在应用程序的主类中大量设置针对特定功能领域的配置设置。
假设你用的是 Spring Data MongoDB,依赖它的自动配置,并且你已经启用了审计功能。
你可以定义你的@SpringBootApplication如下:
-
Java
-
Kotlin
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.mongodb.config.EnableMongoAuditing;
@SpringBootApplication
@EnableMongoAuditing
public class MyApplication {
// ...
}
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.data.mongodb.config.EnableMongoAuditing
@SpringBootApplication
@EnableMongoAuditing
class MyApplication {
// ...
}
因为这个类是测试的源配置,任何切片测试实际上都试图启用 Mongo 审计,这绝对不是你想做的。
一种推荐方法是将该区域特定的配置移到另一个地方@Configuration课程与你的申请在同一层级,如下示例所示:
-
Java
-
Kotlin
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.config.EnableMongoAuditing;
@Configuration(proxyBeanMethods = false)
@EnableMongoAuditing
public class MyMongoConfiguration {
// ...
}
import org.springframework.context.annotation.Configuration
import org.springframework.data.mongodb.config.EnableMongoAuditing
@Configuration(proxyBeanMethods = false)
@EnableMongoAuditing
class MyMongoConfiguration {
// ...
}
根据你申请的复杂程度,你可能只有一个@Configuration用职业来自定义,或者每个领域用一个职业。
后一种方法可以在必要时启用该功能,如有需要,@Import注解。
请参阅此作指南部分,了解何时需要启用特定功能@Configuration切片测试的课程。 |
测试切片不包括@Configuration扫描的类。
例如,对于一个@WebMvcTest,以下配置不包含给定的WebMvcConfigurer在应用上下文中,测试切片加载的 BEAN:
-
Java
-
Kotlin
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 {
@Bean
public WebMvcConfigurer testConfigurer() {
return new WebMvcConfigurer() {
// ...
};
}
}
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer
@Configuration(proxyBeanMethods = false)
class MyWebConfiguration {
@Bean
fun testConfigurer(): WebMvcConfigurer {
return object : WebMvcConfigurer {
// ...
}
}
}
不过,下面的配置会导致这种习惯WebMvcConfigurer被测试切片加载。
-
Java
-
Kotlin
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Component
public class MyWebMvcConfigurer implements WebMvcConfigurer {
// ...
}
import org.springframework.stereotype.Component
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer
@Component
class MyWebMvcConfigurer : WebMvcConfigurer {
// ...
}
另一个令人困惑的原因是类路径扫描。 假设你把代码结构合理,但你需要扫描一个额外的包。 您的申请可能类似于以下代码:
-
Java
-
Kotlin
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@ComponentScan({ "com.example.app", "com.example.another" })
public class MyApplication {
// ...
}
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.context.annotation.ComponentScan
@SpringBootApplication
@ComponentScan("com.example.app", "com.example.another")
class MyApplication {
// ...
}
这样做实际上会覆盖默认的组件扫描指令,副作用是无论你选择哪种切片,都会扫描这两个包裹。
例如,a@DataJpaTest它似乎会突然扫描你应用的组件和用户配置。
同样,把自定义指令移到独立类是解决这个问题的好方法。
如果这对你来说不可行,你可以创建一个@SpringBootConfiguration在你的测试层级中某个位置,这样它就会被用来代替。
或者,你也可以指定测试的来源,这样就不会再找默认来源了。 |