測試 Spring Boot 應用程式
Spring Boot 應用程式是一個 Spring ApplicationContext,因此除了您通常使用普通 Spring 上下文所做的事情之外,無需做任何特殊的事情來測試它。
外部屬性、日誌記錄和 Spring Boot 的其他功能預設情況下僅在使用 SpringApplication 建立上下文時才安裝到上下文中。 |
Spring Boot 提供了 @SpringBootTest 註解,當您需要 Spring Boot 功能時,它可以作為標準 spring-test @ContextConfiguration 註解的替代方案。該註解透過 建立 測試中使用的 ApplicationContext SpringApplication 來工作。除了 @SpringBootTest 之外,還提供了許多其他註解,用於 測試應用程式的更具體切片。
如果您正在使用 JUnit 4,請不要忘記在測試中新增 @RunWith(SpringRunner.class),否則註解將被忽略。如果您正在使用 JUnit 6,則無需新增等效的 @ExtendWith(SpringExtension.class),因為 @SpringBootTest 和其他 @…Test 註解已經用它進行了註解。 |
預設情況下,@SpringBootTest 不會啟動伺服器。您可以使用 @SpringBootTest 的 webEnvironment 屬性來進一步細化測試的執行方式。
-
MOCK(預設):載入一個 WebApplicationContext並提供一個模擬的 Web 環境。使用此註解時不會啟動嵌入式伺服器。如果類路徑上沒有 Web 環境,此模式會透明地回退到建立常規的非 WebApplicationContext。它可以與@AutoConfigureMockMvc或@AutoConfigureWebTestClient結合使用,用於基於模擬的 Web 應用程式測試。 -
RANDOM_PORT:載入一個WebServerApplicationContext並提供一個真實的 Web 環境。嵌入式伺服器將啟動並監聽隨機埠。 -
DEFINED_PORT:載入一個WebServerApplicationContext並提供一個真實的 Web 環境。嵌入式伺服器將啟動並監聽定義的埠(來自您的application.properties)或預設埠8080。 -
NONE:使用SpringApplication載入一個ApplicationContext,但不提供任何 Web 環境(模擬或其他)。
如果您的測試是 @Transactional,則預設情況下會在每個測試方法結束時回滾事務。但是,由於使用 RANDOM_PORT 或 DEFINED_PORT 隱含地提供了真實的 servlet 環境,HTTP 客戶端和伺服器在單獨的執行緒中執行,因此在單獨的事務中執行。在這種情況下,伺服器上啟動的任何事務都不會回滾。 |
如果您的應用程式對管理伺服器使用不同的埠,則帶有 webEnvironment = WebEnvironment.RANDOM_PORT 的 @SpringBootTest 也會在單獨的隨機埠上啟動管理伺服器。 |
檢測 Web 應用程式型別
如果 Spring MVC 可用,則配置常規的基於 MVC 的應用程式上下文。如果您只有 Spring WebFlux,我們將檢測到並配置基於 WebFlux 的應用程式上下文。
如果兩者都存在,Spring MVC 優先。如果您在這種情況下想要測試響應式 Web 應用程式,則必須設定 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(classes=…) 來指定要載入的 Spring @Configuration。或者,您可能經常在測試中使用巢狀的 @Configuration 類。
在測試 Spring Boot 應用程式時,這通常不是必需的。當您未明確定義主配置時,Spring Boot 的 @*Test 註解會自動搜尋您的主配置。
搜尋演算法從包含測試的包開始向上工作,直到找到用 @SpringBootApplication 或 @SpringBootConfiguration 註解的類。只要您以合理的方式 構建程式碼,通常就能找到您的主要配置。
|
如果您使用 測試註解來測試應用程式的更具體部分,則應避免在 主方法的應用程式類 上新增特定於某個特定區域的配置設定。
|
如果您想自定義主配置,可以使用巢狀的 @TestConfiguration 類。與作為應用程式主配置替代品的巢狀 @Configuration 類不同,巢狀的 @TestConfiguration 類是作為應用程式主配置的補充使用的。
| Spring 的測試框架會在測試之間快取應用程式上下文。因此,只要您的測試共享相同的配置(無論它是如何發現的),載入上下文這個可能耗時的過程只發生一次。 |
使用測試配置主方法
通常,由 @SpringBootTest 發現的測試配置將是您的主要 @SpringBootApplication。在大多數結構良好的應用程式中,此配置類還將包含用於啟動應用程式的 main 方法。
例如,以下是典型 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)
}
在上面的示例中,main 方法除了委託給 SpringApplication.run(Class, String…) 之外,什麼都不做。然而,可以有一個更復雜的 main 方法,在呼叫 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")
}
}
由於 main 方法中的自定義會影響生成的 ApplicationContext,因此您可能還希望使用 main 方法來建立測試中使用的 ApplicationContext。預設情況下,@SpringBootTest 不會呼叫您的 main 方法,而是直接使用該類本身來建立 ApplicationContext。
如果您想更改此行為,可以將 @SpringBootTest 的 useMainMethod 屬性更改為 SpringBootTest.UseMainMethod.ALWAYS 或 SpringBootTest.UseMainMethod.WHEN_AVAILABLE。當設定為 ALWAYS 時,如果找不到 main 方法,則測試將失敗。當設定為 WHEN_AVAILABLE 時,如果 main 方法可用,則將使用它,否則將使用標準載入機制。
例如,以下測試將呼叫 MyApplication 的 main 方法來建立 ApplicationContext。如果主方法設定了額外的配置檔案,那麼在 ApplicationContext 啟動時這些配置檔案將處於活動狀態。
-
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),則需要為其註冊 TypeExcludeFilter。有關詳細資訊,請參閱 TypeExcludeFilter API 文件。 |
匯入的 @TestConfiguration 比內部類 @TestConfiguration 更早處理,並且匯入的 @TestConfiguration 將在任何透過元件掃描找到的配置之前處理。通常來說,這種排序上的差異沒有明顯的效應,但如果您依賴於 bean 覆蓋,則需要注意這一點。 |
使用應用程式引數
如果您的應用程式需要 引數,您可以使用 @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 不會啟動伺服器,而是設定一個模擬環境來測試 Web 端點。
使用 Spring MVC,我們可以使用 MockMvc 查詢我們的 Web 端點。以下整合可用
-
使用 Hamcrest 的常規
MockMvc。 -
MockMvcTester封裝了MockMvc並使用了 AssertJ。 -
RestTestClient,其中MockMvc作為伺服器插入以處理請求。 -
WebTestClient,其中MockMvc作為伺服器插入以處理請求。
以下示例展示了可用的整合
-
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")
}
}
如果您只想關注 Web 層,而不啟動完整的 ApplicationContext,請考慮 改用 @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 呼叫的測試可以透過使用 @AutoConfigureRestTestClient 註解測試類來自動裝配 RestTestClient。
配置的客戶端將相對連結解析到正在執行的伺服器,並附帶一個專用 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,則可以從 RestTestClientResponse 獲得專用斷言,如以下示例所示
-
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")
}
}
如果您的類路徑上有 spring-webflux,您還可以透過使用 @AutoConfigureWebTestClient 註解測試類來自動裝配 WebTestClient。
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 也可以與 模擬環境 一起使用,透過使用 spring-boot-webflux-test 中的 @AutoConfigureWebTestClient 註解您的測試類,從而無需執行伺服器。 |
spring-boot-resttestclient 模組還提供了 TestRestTemplate 工具
-
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 bean,請配置一個 RestTestClientBuilderCustomizer bean。任何此類 bean 都將使用用於建立 RestTestClient 的 RestTestClient.Builder 呼叫。
自定義 WebTestClient
要自定義 WebTestClient bean,請配置一個 WebTestClientBuilderCustomizer bean。任何此類 bean 都將使用用於建立 WebTestClient 的 WebTestClient.Builder 呼叫。
使用 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")
// ...
}
}
使用觀察
如果您使用 spring-boot-micrometer-tracing-test 中的 @AutoConfigureTracing 或 spring-boot-micrometer-metrics-test 中的 @AutoConfigureMetrics 註解 切片測試,它會自動配置一個 ObservationRegistry。
使用指標
無論您的類路徑如何,使用 @SpringBootTest 時,除了記憶體支援的計量器登錄檔外,其他計量器登錄檔都不會自動配置。
如果您需要將指標作為整合測試的一部分匯出到不同的後端,請使用 @AutoConfigureMetrics 註解它。
如果您用 @AutoConfigureMetrics 註解 切片測試,它會自動配置一個記憶體中的 MeterRegistry。切片測試中的資料匯出不支援 @AutoConfigureMetrics 註解。
使用追蹤
無論您的類路徑如何,在使用 @SpringBootTest 時,報告資料的追蹤元件都不會自動配置。
如果您需要這些元件作為整合測試的一部分,請使用 @AutoConfigureTracing 註解測試。
如果您建立了自己的報告元件(例如自定義的 SpanExporter 或 brave.handler.SpanHandler),並且不希望它們在測試中啟用,則可以使用 @ConditionalOnEnabledTracingExport 註解來停用它們。
如果您使用 @AutoConfigureTracing 註解 切片測試,它會自動配置一個無操作的 Tracer。切片測試中的資料匯出不支援 @AutoConfigureTracing 註解。
模擬和偵察 Bean
在執行測試時,有時需要在應用程式上下文中模擬某些元件。例如,您可能在開發期間有一個遠端服務的門面,該服務不可用。當您想要模擬在真實環境中難以觸發的故障時,模擬也很有用。
Spring Framework 包含一個 @MockitoBean 註解,可用於在您的 ApplicationContext 中為 bean 定義 Mockito 模擬。此外,@MockitoSpyBean 可用於定義 Mockito 偵察。在 Spring Framework 文件 中瞭解有關這些功能的更多資訊。
自動配置的測試
Spring Boot 的自動配置系統非常適用於應用程式,但有時對於測試來說可能有點太多了。通常,只加載測試應用程式“切片”所需的配置部分會很有幫助。例如,您可能希望測試 Spring MVC 控制器是否正確對映 URL,並且您不希望在這些測試中涉及資料庫呼叫,或者您可能希望測試 JPA 實體,並且在這些測試執行時您對 Web 層不感興趣。
當與 spring-boot-test-autoconfigure 結合使用時,Spring Boot 的 測試模組 包含許多註解,可用於自動配置此類“切片”。它們中的每一個都以類似的方式工作,提供一個 @...Test 註解來載入 ApplicationContext 和一個或多個 @AutoConfigure... 註解,可用於自定義自動配置設定。
每個切片都將元件掃描限制為適當的元件,並載入一組非常受限的自動配置類。如果您需要排除其中一個,大多數 @...Test 註解都提供了一個 excludeAutoConfiguration 屬性。或者,您可以使用 @ImportAutoConfiguration#exclude。 |
不支援在一個測試中使用多個 @...Test 註解來包含多個“切片”。如果您需要多個“切片”,請選擇其中一個 @...Test 註解,並手動包含其他“切片”的 @AutoConfigure... 註解。 |
也可以將 @AutoConfigure... 註解與標準 @SpringBootTest 註解一起使用。如果您對應用程式的“切片”不感興趣,但需要一些自動配置的測試 bean,則可以使用此組合。 |
自動配置的 JSON 測試
為了測試物件 JSON 序列化和反序列化是否按預期工作,您可以使用 spring-boot-test-autoconfigure 模組中的 @JsonTest 註解。@JsonTest 自動配置可用的受支援 JSON 對映器,可以是以下庫之一
-
Jackson
JsonMapper、任何@JacksonComponentbean 和任何 JacksonJacksonModule -
Jackson 2(已棄用)
ObjectMapper、任何@JsonComponentbean 和任何 JacksonModule -
Gson -
Jsonb
如果需要配置自動配置的元素,可以使用 @AutoConfigureJsonTesters 註解。
Spring Boot 包含了基於 AssertJ 的輔助工具,可與 JSONAssert 和 JsonPath 庫一起使用,以檢查 JSON 是否符合預期。JacksonTester、GsonTester、JsonbTester 和 BasicJsonTester 類分別用於 Jackson、Gson、Jsonb 和 String。在使用 @JsonTest 時,測試類上的任何輔助欄位都可以 @Autowired。以下示例展示了 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 輔助類也可以直接在標準單元測試中使用。為此,如果您不使用 @JsonTest,請在您的 @BeforeEach 方法中呼叫輔助工具的 initFields 方法。 |
如果您使用 Spring Boot 基於 AssertJ 的輔助工具來斷言給定 JSON 路徑上的數值,您可能無法根據型別使用 isEqualTo。相反,您可以使用 AssertJ 的 satisfies 來斷言該值符合給定條件。例如,以下示例斷言實際數字是一個浮點值,接近 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))
})
}
自動配置的 Spring MVC 測試
為了測試 Spring MVC 控制器是否按預期工作,請使用 spring-boot-webmvc-test 模組中的 @WebMvcTest 註解。@WebMvcTest 自動配置 Spring MVC 基礎架構,並將掃描的 bean 限制為 @Controller、@ControllerAdvice、@JacksonComponent、@JsonComponent(已棄用)、Converter、GenericConverter、Filter、HandlerInterceptor、WebMvcConfigurer、WebMvcRegistrations 和 HandlerMethodArgumentResolver。當使用 @WebMvcTest 註解時,不會掃描常規的 @Component 和 @ConfigurationProperties bean。@EnableConfigurationProperties 可用於包含 @ConfigurationProperties bean。
由 @WebMvcTest 啟用的自動配置設定列表可以在 附錄 中找到。 |
如果您需要註冊額外的元件,例如 JacksonModule,您可以使用測試中的 @Import 匯入額外的配置類。 |
通常,@WebMvcTest 僅限於單個控制器,並與 @MockitoBean 結合使用,為所需的協作器提供模擬實現。
@WebMvcTest 還會自動配置 MockMvc。Mock MVC 提供了一種強大的方式來快速測試 MVC 控制器,而無需啟動完整的 HTTP 伺服器。如果 AssertJ 可用,則 MockMvcTester 提供的 AssertJ 支援也會自動配置。
您還可以在非 @WebMvcTest(例如 @SpringBootTest)中透過使用 @AutoConfigureMockMvc 註解來自動配置 MockMvc 和 MockMvcTester。以下示例使用 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")
}
}
如果您需要配置自動配置的元素(例如,何時應用 servlet 過濾器),您可以使用 @AutoConfigureMockMvc 註解中的屬性。 |
如果您使用 HtmlUnit 和 Selenium,自動配置還會提供一個 HtmlUnit WebClient bean 和/或一個 Selenium WebDriver bean。以下示例使用 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 bean 放入特殊的“作用域”中,以確保驅動程式在每個測試後退出並注入新例項。如果您不希望這種行為,您可以將 @Scope(ConfigurableBeanFactory.SCOPE_SINGLETON) 新增到您的 WebDriver @Bean 定義中。 |
Spring Boot 建立的 webDriver 作用域將替換任何使用者定義的同名作用域。如果您定義了自己的 webDriver 作用域,您可能會發現在使用 @WebMvcTest 時它會停止工作。 |
如果您的類路徑上有 Spring Security,@WebMvcTest 也會掃描 WebSecurityConfigurer bean。與其完全停用此類測試的安全性,不如使用 Spring Security 的測試支援。有關如何使用 Spring Security 的 MockMvc 支援的更多詳細資訊,請參閱本 使用 Spring Security 進行測試“操作指南”部分。
| 有時編寫 Spring MVC 測試是不夠的;Spring Boot 可以幫助您執行 帶有實際伺服器的完整端到端測試。 |
自動配置的 Spring WebFlux 測試
為了測試 Spring WebFlux 控制器是否按預期工作,您可以使用 spring-boot-webflux-test 模組中的 @WebFluxTest 註解。@WebFluxTest 自動配置 Spring WebFlux 基礎架構,並將掃描的 bean 限制為 @Controller、@ControllerAdvice、@JacksonComponent、@JsonComponent(已棄用)、Converter、GenericConverter 和 WebFluxConfigurer。當使用 @WebFluxTest 註解時,不會掃描常規的 @Component 和 @ConfigurationProperties bean。@EnableConfigurationProperties 可用於包含 @ConfigurationProperties bean。
由 @WebFluxTest 啟用的自動配置列表可以在 附錄 中找到。 |
如果您需要註冊額外的元件,例如 JacksonModule,您可以使用測試中的 @Import 匯入額外的配置類。 |
通常,@WebFluxTest 僅限於單個控制器,並與 @MockitoBean 註解結合使用,為所需的協作器提供模擬實現。
@WebFluxTest 還會自動配置 WebTestClient,它提供了一種強大的方式來快速測試 WebFlux 控制器,而無需啟動完整的 HTTP 伺服器。
您還可以在非 @WebFluxTest(例如 @SpringBootTest)中透過使用 @AutoConfigureWebTestClient 註解來自動配置 WebTestClient。 |
以下示例展示了一個同時使用 @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 應用程式支援,因為在模擬 Web 應用程式中使用 WebTestClient 僅適用於 WebFlux。 |
@WebFluxTest 無法檢測透過函式式 Web 框架註冊的路由。為了在上下文中測試 RouterFunction bean,請考慮使用 @Import 或 @SpringBootTest 自行匯入您的 RouterFunction。 |
@WebFluxTest 無法檢測作為 @Bean 型別 SecurityWebFilterChain 註冊的自定義安全配置。要在測試中包含它,您需要使用 @Import 或 @SpringBootTest 匯入註冊該 bean 的配置。 |
| 有時編寫 Spring WebFlux 測試是不夠的;Spring Boot 可以幫助您執行 帶有實際伺服器的完整端到端測試。 |
自動配置的 Spring GraphQL 測試
Spring GraphQL 提供了一個專門的測試支援模組;您需要將其新增到您的專案中
<dependencies>
<dependency>
<groupId>org.springframework.graphql</groupId>
<artifactId>spring-graphql-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Unless already present in the compile scope -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
dependencies {
testImplementation("org.springframework.graphql:spring-graphql-test")
// Unless already present in the implementation configuration
testImplementation("org.springframework.boot:spring-boot-starter-webflux")
}
此測試模組附帶 GraphQlTester。測試器在測試中大量使用,因此請務必熟悉它的使用。有 GraphQlTester 變體,Spring Boot 將根據測試型別自動配置它們
-
ExecutionGraphQlServiceTester在伺服器端執行測試,不涉及客戶端或傳輸 -
HttpGraphQlTester使用連線到伺服器的客戶端執行測試,無論是否有即時伺服器
Spring Boot 幫助您使用 spring-boot-graphql-test 模組中的 @GraphQlTest 註解測試您的 Spring GraphQL 控制器。@GraphQlTest 自動配置 Spring GraphQL 基礎設施,不涉及任何傳輸或伺服器。這會將掃描的 bean 限制為 @Controller、RuntimeWiringConfigurer、JacksonComponent、@JsonComponent(已棄用)、Converter、GenericConverter、DataFetcherExceptionResolver、Instrumentation 和 GraphQlSourceBuilderCustomizer。當使用 @GraphQlTest 註解時,不會掃描常規的 @Component 和 @ConfigurationProperties bean。@EnableConfigurationProperties 可用於包含 @ConfigurationProperties bean。
由 @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 測試是完整的整合測試,涉及整個應用程式。可以透過使用 spring-boot-graphql-test 模組中的 @AutoConfigureHttpGraphQlTester 註解您的測試類來新增 HttpGraphQlTester bean
-
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!")
}
}
HttpGraphQlTester bean 使用整合測試的相關傳輸。當使用隨機或定義埠時,測試器會針對即時伺服器進行配置。要將測試器繫結到 MockMvc,請確保使用 @AutoConfigureMockMvc 註解您的測試類。
自動配置的資料 Cassandra 測試
您可以使用 spring-boot-data-cassandra-test 模組中的 @DataCassandraTest 來測試 Data Cassandra 應用程式。預設情況下,它配置一個 CassandraTemplate,掃描 @Table 類,並配置 Spring Data Cassandra 儲存庫。當使用 @DataCassandraTest 註解時,不會掃描常規的 @Component 和 @ConfigurationProperties bean。@EnableConfigurationProperties 可用於包含 @ConfigurationProperties bean。(有關將 Cassandra 與 Spring Boot 一起使用的更多資訊,請參閱 Cassandra。)
由 @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 測試
您可以使用 spring-boot-data-couchbase-test 模組中的 @DataCouchbaseTest 來測試 Data Couchbase 應用程式。預設情況下,它配置一個 CouchbaseTemplate 或 ReactiveCouchbaseTemplate,掃描 @Document 類,並配置 Spring Data Couchbase 儲存庫。當使用 @DataCouchbaseTest 註解時,不會掃描常規的 @Component 和 @ConfigurationProperties bean。@EnableConfigurationProperties 可用於包含 @ConfigurationProperties bean。(有關將 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) {
// ...
}
自動配置的資料 Elasticsearch 測試
您可以使用 spring-boot-data-elasticsearch-test 模組中的 @DataElasticsearchTest 來測試資料 Elasticsearch 應用程式。預設情況下,它配置一個 ElasticsearchTemplate,掃描 @Document 類,並配置 Spring Data Elasticsearch 儲存庫。當使用 @DataElasticsearchTest 註解時,不會掃描常規的 @Component 和 @ConfigurationProperties bean。@EnableConfigurationProperties 可用於包含 @ConfigurationProperties bean。(有關將 Elasticsearch 與 Spring Boot 一起使用的更多資訊,請參閱本章前面提到的 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 測試
您可以使用 spring-boot-data-jpa-test 模組中的 @DataJpaTest 註解來測試資料 JPA 應用程式。預設情況下,它掃描 @Entity 類並配置 Spring Data JPA 儲存庫。如果類路徑上存在嵌入式資料庫,它也會配置一個。透過將 spring.jpa.show-sql 屬性設定為 true,預設情況下會記錄 SQL 查詢。可以使用註解的 showSql 屬性停用此功能。
當使用 @DataJpaTest 註解時,不會掃描常規的 @Component 和 @ConfigurationProperties bean。@EnableConfigurationProperties 可用於包含 @ConfigurationProperties bean。
由 @DataJpaTest 啟用的自動配置設定列表可以在 附錄 中找到。 |
預設情況下,資料 JPA 測試是事務性的,並在每個測試結束時回滾。有關更多詳細資訊,請參閱 Spring Framework 參考文件中的 相關部分。如果您不希望這樣,可以按如下方式停用測試或整個類的事務管理
-
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 測試還可以注入一個 TestEntityManager bean,它提供了標準 JPA EntityManager 的替代方案,專門用於測試。
TestEntityManager 也可以透過新增 @AutoConfigureTestEntityManager 自動配置到您的任何基於 Spring 的測試類。這樣做時,請確保您的測試在事務中執行,例如透過在測試類或方法上新增 @Transactional。 |
如果需要,還可以使用 JdbcTemplate。以下示例展示了正在使用的 @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 測試
spring-boot-jdbc-test 模組中的 @JdbcTest 類似於 @DataJdbcTest,但適用於僅需要 DataSource 且不使用 Spring Data JDBC 的測試。預設情況下,它配置一個記憶體嵌入式資料庫和一個 JdbcTemplate。當使用 @JdbcTest 註解時,不會掃描常規的 @Component 和 @ConfigurationProperties bean。@EnableConfigurationProperties 可用於包含 @ConfigurationProperties bean。
預設情況下,JDBC 測試是事務性的,並在每個測試結束時回滾。有關更多詳細資訊,請參閱 Spring Framework 參考文件中的 相關部分。如果您不希望這樣,可以按如下方式停用測試或整個類的事務管理
-
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 測試
spring-boot-data-jdbc-test 模組中的 @DataJdbcTest 類似於 @JdbcTest,但適用於使用 Spring Data JDBC 儲存庫的測試。預設情況下,它配置一個記憶體嵌入式資料庫、一個 JdbcTemplate 和 Spring Data JDBC 儲存庫。當使用 @DataJdbcTest 註解時,僅掃描 AbstractJdbcConfiguration 子類,不掃描常規的 @Component 和 @ConfigurationProperties bean。@EnableConfigurationProperties 可用於包含 @ConfigurationProperties bean。
由 @DataJdbcTest 啟用的自動配置列表可以在 附錄 中找到。 |
預設情況下,資料 JDBC 測試是事務性的,並在每個測試結束時回滾。有關更多詳細資訊,請參閱 Spring Framework 參考文件中的 相關部分。如果您不希望這樣,可以像 JDBC 示例中所示 停用測試或整個測試類的事務管理。
如果您更喜歡針對真實資料庫執行測試,可以使用 @AutoConfigureTestDatabase 註解,其方式與 @DataJpaTest 相同。(請參閱 自動配置的資料 JPA 測試。)
自動配置的資料 R2DBC 測試
spring-boot-data-r2dbc-test 模組中的 @DataR2dbcTest 類似於 @DataJdbcTest,但適用於使用 Spring Data R2DBC 儲存庫的測試。預設情況下,它配置一個記憶體嵌入式資料庫、一個 R2dbcEntityTemplate 和 Spring Data R2DBC 儲存庫。當使用 @DataR2dbcTest 註解時,不會掃描常規的 @Component 和 @ConfigurationProperties bean。@EnableConfigurationProperties 可用於包含 @ConfigurationProperties bean。
由 @DataR2dbcTest 啟用的自動配置列表可以在 附錄 中找到。 |
預設情況下,資料 R2DBC 測試不具有事務性。
如果您更喜歡針對真實資料庫執行測試,可以使用 @AutoConfigureTestDatabase 註解,其方式與 @DataJpaTest 相同。(請參閱 自動配置的資料 JPA 測試。)
自動配置的 jOOQ 測試
您可以以類似於 @JdbcTest 的方式使用 spring-boot-jooq-test 中的 @JooqTest,但適用於 jOOQ 相關測試。由於 jOOQ 嚴重依賴於與資料庫模式對應的基於 Java 的模式,因此使用了現有的 DataSource。如果您想用記憶體資料庫替換它,可以使用 @AutoConfigureTestDatabase 覆蓋這些設定。(有關將 jOOQ 與 Spring Boot 一起使用的更多資訊,請參閱 使用 jOOQ。)當使用 @JooqTest 註解時,不會掃描常規的 @Component 和 @ConfigurationProperties bean。@EnableConfigurationProperties 可用於包含 @ConfigurationProperties bean。
@JooqTest 配置了一個 DSLContext。以下示例展示了正在使用的 @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 測試
您可以使用 spring-boot-data-mongodb-test 模組中的 @DataMongoTest 來測試 MongoDB 應用程式。預設情況下,它配置一個 MongoTemplate,掃描 @Document 類,並配置 Spring Data MongoDB 儲存庫。當使用 @DataMongoTest 註解時,不會掃描常規的 @Component 和 @ConfigurationProperties bean。@EnableConfigurationProperties 可用於包含 @ConfigurationProperties bean。(有關將 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) {
// ...
}
自動配置的 Data Neo4j 測試
你可以使用 spring-boot-data-neo4j-test 模組中的 @DataNeo4jTest 來測試 Neo4j 應用程式。預設情況下,它會掃描 @Node 類,並配置 Spring Data Neo4j 儲存庫。當使用 @DataNeo4jTest 註解時,不會掃描常規的 @Component 和 @ConfigurationProperties bean。@EnableConfigurationProperties 可用於包含 @ConfigurationProperties bean。(有關將 Neo4J 與 Spring Boot 結合使用的更多資訊,請參閱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 測試是事務性的,並在每個測試結束時回滾。有關更多詳細資訊,請參閱 Spring Framework 參考文件中的相關部分。如果這不是你想要的,你可以按如下方式停用測試或整個類的事務管理
-
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 測試
你可以使用 spring-boot-data-redis-test 模組中的 @DataRedisTest 來測試 Data Redis 應用程式。預設情況下,它會掃描 @RedisHash 類並配置 Spring Data Redis 儲存庫。當使用 @DataRedisTest 註解時,不會掃描常規的 @Component 和 @ConfigurationProperties bean。@EnableConfigurationProperties 可用於包含 @ConfigurationProperties bean。(有關將 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) {
// ...
}
自動配置的 Data LDAP 測試
你可以使用 @DataLdapTest 來測試 Data LDAP 應用程式。預設情況下,它會配置一個記憶體中的嵌入式 LDAP(如果可用),配置一個 LdapTemplate,掃描 @Entry 類,並配置 Spring Data LDAP 儲存庫。當使用 @DataLdapTest 註解時,不會掃描常規的 @Component 和 @ConfigurationProperties bean。@EnableConfigurationProperties 可用於包含 @ConfigurationProperties bean。(有關將 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 客戶端
你可以使用 spring-boot-restclient-test 模組中的 @RestClientTest 註解來測試 REST 客戶端。預設情況下,它會自動配置 Jackson、GSON 和 Jsonb 支援,配置一個 RestTemplateBuilder 和一個 RestClient.Builder,並新增對 MockRestServiceServer 的支援。當使用 @RestClientTest 註解時,不會掃描常規的 @Component 和 @ConfigurationProperties bean。@EnableConfigurationProperties 可用於包含 @ConfigurationProperties bean。
有關 @RestClientTest 啟用的自動配置設定列表,請參見附錄。 |
要測試的特定 bean 應透過使用 @RestClientTest 的 value 或 components 屬性來指定。
當在被測試的 bean 中使用 RestTemplateBuilder 並且在構建 RestTemplate 時呼叫了 RestTemplateBuilder.rootUri(String rootUri) 時,根 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")
}
}
當在被測試的 bean 中使用 RestClient.Builder 時,或者在使用 RestTemplateBuilder 但未呼叫 rootUri(String rootURI) 時,必須在 MockRestServiceServer 預期中使用完整 URI,如以下示例所示
-
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")
}
}
自動配置的 Web 客戶端
你可以使用 spring-boot-webclient-test 模組中的 @WebClientTest 註解來測試使用 WebClient 的程式碼。預設情況下,它會自動配置 Jackson、GSON 和 Jsonb 支援,並配置一個 WebClient.Builder。當使用 @WebClientTest 註解時,不會掃描常規的 @Component 和 @ConfigurationProperties bean。@EnableConfigurationProperties 可用於包含 @ConfigurationProperties bean。
有關 @WebClientTest 啟用的自動配置設定列表,請參見附錄。 |
要測試的特定 bean 應透過使用 @WebClientTest 的 value 或 components 屬性來指定。
自動配置的 Spring REST Docs 測試
你可以使用 `spring-boot-restdocs-` 模組中的 @AutoConfigureRestDocs 註解來在你的測試中使用 Mock MVC 或 WebTestClient 進行 Spring REST Docs。它消除了 Spring REST Docs 中對 JUnit 擴充套件的需求。
@AutoConfigureRestDocs 可用於覆蓋預設輸出目錄(如果你使用 Maven,則為 target/generated-snippets;如果你使用 Gradle,則為 build/generated-snippets)。它還可以用於配置任何文件 URI 中出現的主機、方案和埠。
使用 Mock MVC 的自動配置 Spring REST Docs 測試
在測試基於 Servlet 的 Web 應用程式時,@AutoConfigureRestDocs 會定製 MockMvc bean 以使用 Spring REST Docs。你可以透過使用 @Autowired 注入它,並在你的測試中像通常使用 Mock MVC 和 Spring REST Docs 時一樣使用它,如以下示例所示
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.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"));
}
}
兩者在幕後都重用相同的 MockMvc 例項,因此對其進行的任何配置都適用於兩者。
如果你需要比 @AutoConfigureRestDocs 的屬性提供的更多控制來配置 Spring REST Docs,你可以使用 RestDocsMockMvcConfigurationCustomizer bean,如以下示例所示
-
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 bean。自動配置會使用此結果處理器呼叫 alwaysDo,從而導致每次 MockMvc 呼叫都會自動生成預設片段。以下示例展示了 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}")
}
}
使用 WebTestClient 的自動配置 Spring REST Docs 測試
在測試響應式 Web 應用程式時,@AutoConfigureRestDocs 也可以與 WebTestClient 一起使用。你可以透過使用 @Autowired 注入它,並在你的測試中像通常使用 @WebFluxTest 和 Spring REST Docs 時一樣使用它,如以下示例所示
-
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"))
}
}
如果你需要比 @AutoConfigureRestDocs 的屬性提供的更多控制來配置 Spring REST Docs,你可以使用 RestDocsWebTestClientConfigurationCustomizer bean,如以下示例所示
-
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 Services 測試
自動配置的 Spring Web Services 客戶端測試
你可以使用 spring-boot-webservices-test 模組中的 @WebServiceClientTest 來測試使用 Spring Web Services 專案呼叫 Web 服務的應用程式。預設情況下,它會配置一個 MockWebServiceServer bean 並自動自定義你的 WebServiceTemplateBuilder。(有關將 Web Services 與 Spring Boot 結合使用的更多資訊,請參閱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 伺服器測試
你可以使用 spring-boot-webservices-test 模組中的 @WebServiceServerTest 來測試使用 Spring Web Services 專案實現 Web 服務的應用程式。預設情況下,它會配置一個 MockWebServiceClient bean,可用於呼叫你的 Web 服務端點。(有關將 Web Services 與 Spring Boot 結合使用的更多資訊,請參閱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 以特定方式處理。 |
或者,可以透過在 META-INF/spring 中儲存的檔案中註冊它們,為任何切片註解的使用新增附加自動配置,如以下示例所示
com.example.IntegrationAutoConfiguration
在此示例中,com.example.IntegrationAutoConfiguration 在每個使用 @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 {
// ...
}
這樣做會有效地覆蓋預設元件掃描指令,其副作用是無論你選擇哪個切片,都會掃描這兩個包。例如,@DataJpaTest 似乎突然掃描了你的應用程式的元件和使用者配置。同樣,將自定義指令移動到單獨的類是解決此問題的好方法。
如果這不是你的選擇,你可以在測試的層次結構中的某個位置建立一個 @SpringBootConfiguration,以便它被使用。或者,你可以為你的測試指定一個源,這會停用查詢預設源的行為。 |