測試工具
一些在測試您的應用程式時通常很有用的測試工具類別,已封裝為 spring-boot
的一部分。
ConfigDataApplicationContextInitializer
ConfigDataApplicationContextInitializer
是一個 ApplicationContextInitializer
,您可以將其應用於您的測試,以載入 Spring Boot application.properties
檔案。當您不需要 @SpringBootTest
提供的全套功能時,可以使用它,如下列範例所示
-
Java
-
Kotlin
import org.springframework.boot.test.context.ConfigDataApplicationContextInitializer;
import org.springframework.test.context.ContextConfiguration;
@ContextConfiguration(classes = Config.class, initializers = ConfigDataApplicationContextInitializer.class)
class MyConfigFileTests {
// ...
}
import org.springframework.boot.test.context.ConfigDataApplicationContextInitializer
import org.springframework.test.context.ContextConfiguration
@ContextConfiguration(classes = [Config::class], initializers = [ConfigDataApplicationContextInitializer::class])
class MyConfigFileTests {
// ...
}
單獨使用 ConfigDataApplicationContextInitializer 不會提供對 @Value("${…}") 注入的支援。它唯一的工作是確保 application.properties 檔案已載入到 Spring 的 Environment 中。為了獲得 @Value 支援,您需要額外組態 PropertySourcesPlaceholderConfigurer ,或使用 @SpringBootTest ,後者會為您自動組態一個。 |
TestPropertyValues
TestPropertyValues
讓您可以快速將屬性新增至 ConfigurableEnvironment
或 ConfigurableApplicationContext
。您可以使用 key=value
字串呼叫它,如下所示
-
Java
-
Kotlin
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.mock.env.MockEnvironment;
import static org.assertj.core.api.Assertions.assertThat;
class MyEnvironmentTests {
@Test
void testPropertySources() {
MockEnvironment environment = new MockEnvironment();
TestPropertyValues.of("org=Spring", "name=Boot").applyTo(environment);
assertThat(environment.getProperty("name")).isEqualTo("Boot");
}
}
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.springframework.boot.test.util.TestPropertyValues
import org.springframework.mock.env.MockEnvironment
class MyEnvironmentTests {
@Test
fun testPropertySources() {
val environment = MockEnvironment()
TestPropertyValues.of("org=Spring", "name=Boot").applyTo(environment)
assertThat(environment.getProperty("name")).isEqualTo("Boot")
}
}
OutputCapture
OutputCapture
是一個 JUnit Extension
,您可以使用它來擷取 System.out
和 System.err
輸出。若要使用它,請新增 @ExtendWith(OutputCaptureExtension.class)
並將 CapturedOutput
作為引數注入到您的測試類別建構子或測試方法中,如下所示
-
Java
-
Kotlin
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.test.system.CapturedOutput;
import org.springframework.boot.test.system.OutputCaptureExtension;
import static org.assertj.core.api.Assertions.assertThat;
@ExtendWith(OutputCaptureExtension.class)
class MyOutputCaptureTests {
@Test
void testName(CapturedOutput output) {
System.out.println("Hello World!");
assertThat(output).contains("World");
}
}
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.springframework.boot.test.system.CapturedOutput
import org.springframework.boot.test.system.OutputCaptureExtension
@ExtendWith(OutputCaptureExtension::class)
class MyOutputCaptureTests {
@Test
fun testName(output: CapturedOutput?) {
println("Hello World!")
assertThat(output).contains("World")
}
}
TestRestTemplate
TestRestTemplate
是 Spring 的 RestTemplate
的便利替代方案,在整合測試中很有用。您可以取得原始範本,或發送 Basic HTTP 驗證(使用使用者名稱和密碼)的範本。在任何一種情況下,該範本都是容錯的。這表示它的行為方式是測試友善的,不會在 4xx 和 5xx 錯誤時拋出例外。相反地,可以透過傳回的 ResponseEntity
及其狀態碼來偵測到此類錯誤。
Spring Framework 5.0 提供了一個新的 WebTestClient ,適用於 WebFlux 整合測試 以及 WebFlux 和 MVC 端對端測試。它提供了用於斷言的 Fluent API,不同於 TestRestTemplate 。 |
建議(但非強制性)使用 Apache HTTP Client(版本 5.1 或更好)。如果您在類別路徑中有該用戶端,則 TestRestTemplate
會透過適當地組態用戶端來回應。如果您確實使用 Apache 的 HTTP 用戶端,則會啟用一些額外的測試友善功能
-
不會跟隨重定向(因此您可以斷言回應位置)。
-
Cookie 會被忽略(因此範本是無狀態的)。
TestRestTemplate
可以直接在您的整合測試中實例化,如下列範例所示
-
Java
-
Kotlin
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.ResponseEntity;
import static org.assertj.core.api.Assertions.assertThat;
class MyTests {
private final TestRestTemplate template = new TestRestTemplate();
@Test
void testRequest() {
ResponseEntity<String> headers = this.template.getForEntity("https://myhost.example.com/example", String.class);
assertThat(headers.getHeaders().getLocation()).hasHost("other.example.com");
}
}
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.springframework.boot.test.web.client.TestRestTemplate
class MyTests {
private val template = TestRestTemplate()
@Test
fun testRequest() {
val headers = template.getForEntity("https://myhost.example.com/example", String::class.java)
assertThat(headers.headers.location).hasHost("other.example.com")
}
}
或者,如果您將 @SpringBootTest
注解與 WebEnvironment.RANDOM_PORT
或 WebEnvironment.DEFINED_PORT
一起使用,則可以注入完全組態的 TestRestTemplate
並開始使用它。必要時,可以透過 RestTemplateBuilder
Bean 應用額外自訂。任何未指定主機和埠號的 URL 都會自動連接到嵌入式伺服器,如下列範例所示
-
Java
-
Kotlin
import java.time.Duration;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpHeaders;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class MySpringBootTests {
@Autowired
private TestRestTemplate template;
@Test
void testRequest() {
HttpHeaders headers = this.template.getForEntity("/example", String.class).getHeaders();
assertThat(headers.getLocation()).hasHost("other.example.com");
}
@TestConfiguration(proxyBeanMethods = false)
static class RestTemplateBuilderConfiguration {
@Bean
RestTemplateBuilder restTemplateBuilder() {
return new RestTemplateBuilder().setConnectTimeout(Duration.ofSeconds(1))
.setReadTimeout(Duration.ofSeconds(1));
}
}
}
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.test.context.TestConfiguration
import org.springframework.boot.test.web.client.TestRestTemplate
import org.springframework.boot.web.client.RestTemplateBuilder
import org.springframework.context.annotation.Bean
import java.time.Duration
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class MySpringBootTests(@Autowired val template: TestRestTemplate) {
@Test
fun testRequest() {
val headers = template.getForEntity("/example", String::class.java).headers
assertThat(headers.location).hasHost("other.example.com")
}
@TestConfiguration(proxyBeanMethods = false)
internal class RestTemplateBuilderConfiguration {
@Bean
fun restTemplateBuilder(): RestTemplateBuilder {
return RestTemplateBuilder().setConnectTimeout(Duration.ofSeconds(1))
.setReadTimeout(Duration.ofSeconds(1))
}
}
}