测试实用程序
spring-boot
包含一些测试实用程序类,这些类在测试应用程序时通常很有用。
ConfigDataApplicationContextInitializer
ConfigDataApplicationContextInitializer
是一个 ApplicationContextInitializer
,您可以将其应用于您的测试以加载 Spring Boot application.properties
文件。当您不需要 @SpringBootTest
提供的全部功能集时,可以使用它,如下面的示例所示
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
字符串调用它,如下所示
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");
}
}
OutputCapture
OutputCapture
是一个 JUnit Extension
,您可以使用它来捕获 System.out
和 System.err
输出。要使用它,请添加 @ExtendWith(OutputCaptureExtension.class)
并将 CapturedOutput
作为参数注入到您的测试类构造函数或测试方法中,如下所示
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");
}
}
TestRestTemplate
TestRestTemplate
是 Spring 的 RestTemplate
的一个便捷替代方案,在集成测试中很有用。您可以获得一个普通模板或一个发送基本 HTTP 身份验证(使用用户名和密码)的模板。在这两种情况下,模板都是容错的。这意味着它以测试友好的方式运行,不会在 4xx 和 5xx 错误上抛出异常。相反,可以通过返回的 ResponseEntity
及其状态代码检测到此类错误。
Spring Framework 5.0 提供了一个新的 WebTestClient ,它适用于 WebFlux 集成测试 以及 WebFlux 和 MVC 端到端测试。与 TestRestTemplate 不同,它提供了一个用于断言的流畅 API。
|
建议使用 Apache HTTP Client(版本 5.1 或更高版本),但不是强制性的。如果您在类路径中拥有它,TestRestTemplate
会通过适当地配置客户端来响应。如果您确实使用了 Apache 的 HTTP 客户端,则会启用一些额外的测试友好功能
-
不会跟随重定向(因此您可以断言响应位置)。
-
忽略 cookie(因此模板是无状态的)。
TestRestTemplate
可以直接在您的集成测试中实例化,如下例所示
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");
}
}
或者,如果您使用 @SpringBootTest
注解以及 WebEnvironment.RANDOM_PORT
或 WebEnvironment.DEFINED_PORT
,您可以注入一个完全配置的 TestRestTemplate
并开始使用它。如果需要,可以通过 RestTemplateBuilder
bean 应用额外的自定义配置。任何未指定主机和端口的 URL 会自动连接到嵌入式服务器,如下例所示
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));
}
}
}