1.4.1. ConfigFileApplicationContextInitializer
1.4.2. TestPropertyValues
1.4.3. OutputCapture
1.4.4. TestRestTemplate
Spring Boot提供了许多实用程序和注解来帮助你测试应用程序。测试支持由两个模块提供:
spring-boot-test
包含核心项,
spring-boot-test-autoconfigure
支持测试的自动配置。
1.1. 测试范围依赖性
spring-boot-starter-test
“Starter”(在测试
test
scope
内)包含以下提供的库:
通常,你需要超越单元测试并开始集成测试(使用Spring
ApplicationContext
)。能够在不需要部署应用程序或需要连接到其他基础设施
的情况下执行集成测试非常有用。
Spring框架包含一个用于此类集成测试的专用测试模块。你可以直接声明该依赖项:
org.springframework:spring-test
或使用
spring-boot-starter-test
“Starter”来传递它。
如果你之前没有使用过Spring测试模块,那么首先应阅读
Spring框架参考文档
的相关部分。
1.3. 测试Spring Boot应用程序
Spring Boot应用程序是一个Spring
ApplicationContext
,因此除了通常使用的Spring上下文之外,还没有什么特别的东西可以用来测试它。
Spring Boot提供
@SpringBootTest
注解,当你需要Spring Boot功能时,它可以用作标准
spring-test
@ContextConfiguration
注解的替代方法。注解通过
在
SpringApplication
创建测试中使用的
ApplicationContext
来工作
。除了
@SpringBootTest
之外,还提供了许多其他注解来测试应用程序的
更具体的切片
。
MOCK
(默认):加载Web
ApplicationContext
并提供模拟Web环境。使用此批注时,不会启动嵌入式服务器。
如果类路径上没有Web环境,则此模式将透明地回退到创建常规非Web
ApplicationContext
。它可以与
@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客户端和服务器会在不同的线程中运行,因此在单独的事务中运行。在这种情况下,
在服务器上启动的任何事务都不会回滚。
1.3.1. 检测Web应用程序类型
如果Spring MVC可用,则配置基于MVC的常规应用程序上下文。如果你只有Spring WebFlux,我们将检测到并配置基于WebFlux的应用程序上下文。
如果两者都存在,则Spring MVC优先。如果要在此方案中测试响应式Web应用程序,则必须设置
spring.main.web-application-type
属性:
@RunWith(SpringRunner.class)
@SpringBootTest(properties = "spring.main.web-application-type=reactive")
public class MyWebFluxTests { ... }
1.3.2. 检测测试配置
如果你熟悉Spring Test框架,则可能习惯使用
@ContextConfiguration(classes=…)
来指定要加载的Spring
@Configuration
。
或者,你可能经常在测试中使用嵌套的
@Configuration
类。
在测试Spring Boot应用程序时,通常不需要这样做。只要你没有明确定义,Spring Boot的
@*Test
注解会自动搜索你的主要配置。
搜索算法从包含测试的包开始工作,直到找到使用
@SpringBootApplication
或
@SpringBootConfiguration
注解的类。
只要你以合理的方式
结构化代码
,通常就会自动找到主要配置。
如果你的应用程序使用组件扫描(例如,如果你使用
@SpringBootApplication
或
@ComponentScan
),
你可能会发现仅为特定测试创建的顶级配置类会意外地在任何地方被拾取应用。
如前所述
,
@TestConfiguration
可用于测试的内部类以自定义主要配置。当置于顶级类时,
@TestConfiguration
指示不应通过扫描拾取
src/test/java
中的类。
然后,你可以在需要的位置显式导入该类,如以下示例所示:
@RunWith(SpringRunner.class)
@SpringBootTest
@Import(MyTestsConfiguration.class)
public class MyTests {
@Test
public void exampleTest() {
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
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;
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class MockMvcExampleTests {
@Autowired
private MockMvc mvc;
@Test
public void exampleTest() throws Exception {
this.mvc.perform(get("/")).andExpect(status().isOk())
.andExpect(content().string("Hello World"));
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureWebTestClient
public class MockWebTestClientExampleTests {
@Autowired
private WebTestClient webClient;
@Test
public void exampleTest() {
this.webClient.get().uri("/").exchange().expectStatus().isOk()
.expectBody(String.class).isEqualTo("Hello World");
1.3.5. 使用正在运行的服务器进行测试
如果你需要启动完整运行的服务器,我们建议你使用随机端口。如果使用 @SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
,
则每次运行测试时都会随机选择一个可用端口。
@LocalServerPort
注解可用于注入测试中 实际使用的随机端口。
为方便起见,需要对启动的服务器进行REST调用的测试还可以 @Autowire
WebTestClient
,
它解析了与正在运行的服务器的相对链接,并附带了用于验证响应的专用API,如以下示例所示:
import org.junit.Test;
import org.junit.runner.RunWith;
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.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class RandomPortWebTestClientExampleTests {
@Autowired
private WebTestClient webClient;
@Test
public void exampleTest() {
this.webClient.get().uri("/").exchange().expectStatus().isOk()
.expectBody(String.class).isEqualTo("Hello World");
此设置需要类路径上有 spring-webflux
。如果你不能或不愿添加webflux,Spring Boot还提供了一个 TestRestTemplate
工具:
import org.junit.Test;
import org.junit.runner.RunWith;
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.web.client.TestRestTemplate;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class RandomPortTestRestTemplateExampleTests {
@Autowired
private TestRestTemplate restTemplate;
@Test
public void exampleTest() {
String body = this.restTemplate.getForObject("/", String.class);
assertThat(body).isEqualTo("Hello World");
@RunWith(SpringRunner.class)
@SpringBootTest(properties = "spring.jmx.enabled=true")
@DirtiesContext
public class SampleJmxTests {
@Autowired
private MBeanServer mBeanServer;
@Test
public void exampleTest() {
// ...
Spring Boot包含一个 @MockBean
注解,可用于为 ApplicationContext
中的bean定义Mockito模拟。
你可以使用该注解添加新bean或替换单个现有bean定义。该注解可以直接用于测试类,测试中的字段或 @Configuration
类和字段。
在字段上使用时,也会注入创建的模拟实例。每个测试方法结束后,模拟Bean都会自动重置。
如果你的测试使用Spring Boot的测试注解之一(例如 @SpringBootTest
),则会自动启用此功能。
要将此特性用于不同的安排,必须显式地添加侦听器,如下面的示例所示:
@TestExecutionListeners(MockitoTestExecutionListener.class)
。
import org.junit.*;
import org.junit.runner.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.boot.test.context.*;
import org.springframework.boot.test.mock.mockito.*;
import org.springframework.test.context.junit4.*;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.BDDMockito.*;
@RunWith(SpringRunner.class)
@SpringBootTest
public class MyTests {
@MockBean
private RemoteService remoteService;
@Autowired
private Reverser reverser;
@Test
public void exampleTest() {
// RemoteService已注入Reverser bean
given(this.remoteService.someCall()).willReturn("mock");
String reverse = reverser.reverseSomeCall();
assertThat(reverse).isEqualTo("kcom");
此外,你可以使用 @SpyBean
将任何现有bean包装为Mockito间谍。有关详细信息,请参阅 Javadoc。
Spring Boot的自动配置系统适用于应用程序,但有时对于测试来说有点太多了。通常,只需加载测试应用程序“切片”所需的配置部分。
例如,你可能希望测试Spring MVC控制器是否正确映射URL,并且你不希望在这些测试中涉及数据库调用,或者你可能想要测试JPA实体,
并且你对Web层测试运行不感兴趣。
spring-boot-test-autoconfigure
模块包括许多可用于自动配置这种“切片”的注解。它们中的每一个都以类似的方式工作,
提供一个 @…Test
注解,用于加载 ApplicationContext
和一个或多个 @AutoConfigure…
注解,可用于自定义自动配置设置。
Spring Boot包括基于AssertJ的辅助类,它们与JSONAssert和JsonPath库一起使用,以检查JSON是否按预期显示。
JacksonTester
,GsonTester
,JsonbTester
和 BasicJsonTester
类可分别用于Jackson,Gson,Jsonb和Strings。
使用 @JsonTest
时,测试类上的任何被辅助字段都可以标注为 @Autowired
。以下示例显示了Jackson的测试类:
import org.junit.*;
import org.junit.runner.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.boot.test.autoconfigure.json.*;
import org.springframework.boot.test.context.*;
import org.springframework.boot.test.json.*;
import org.springframework.test.context.junit4.*;
import static org.assertj.core.api.Assertions.*;
@RunWith(SpringRunner.class)
@JsonTest
public class MyJsonTests {
@Autowired
private JacksonTester<VehicleDetails> json;
@Test
public void testSerialize() throws Exception {
VehicleDetails details = new VehicleDetails("Honda", "Civic");
// 断言设置了一个与测试处于相同的包中 `.json` 文件
assertThat(this.json.write(details)).isEqualToJson("expected.json");
// 或者使用基于JSON路径的断言
assertThat(this.json.write(details)).hasJsonPathStringValue("@.make");
assertThat(this.json.write(details)).extractingJsonPathStringValue("@.make")
.isEqualTo("Honda");
@Test
public void testDeserialize() 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");
要测试Spring MVC控制器是否按预期工作,请使用 @WebMvcTest
注解。@WebMvcTest
自动配置Spring MVC基础设施并将扫描的bean限制为
@Controller
,@ControllerAdvice
,@JsonComponent
,Converter
,GenericConverter
,Filter
,WebMvcConfigurer
和 HandlerMethodArgumentResolver
。使用此注解时,不会扫描常规 @Component
bean。
import org.junit.*;
import org.junit.runner.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.boot.test.autoconfigure.web.servlet.*;
import org.springframework.boot.test.mock.mockito.*;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.BDDMockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@RunWith(SpringRunner.class)
@WebMvcTest(UserVehicleController.class)
public class MyControllerTests {
@Autowired
private MockMvc mvc;
@MockBean
private UserVehicleService userVehicleService;
@Test
public void testExample() throws Exception {
given(this.userVehicleService.getVehicleDetails("sboot"))
.willReturn(new VehicleDetails("Honda", "Civic"));
this.mvc.perform(get("/sboot/vehicle").accept(MediaType.TEXT_PLAIN))
.andExpect(status().isOk())
.andExpect(content().string("Honda Civic"));
import org.junit.*;
import org.junit.runner.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.boot.test.autoconfigure.web.servlet.*;
import org.springframework.boot.test.mock.mockito.*;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.BDDMockito.*;
@RunWith(SpringRunner.class)
@WebMvcTest(UserVehicleController.class)
public class MyHtmlUnitTests {
@Autowired
private WebClient webClient;
@MockBean
private UserVehicleService userVehicleService;
@Test
public void testExample() throws Exception {
given(this.userVehicleService.getVehicleDetails("sboot"))
.willReturn(new VehicleDetails("Honda", "Civic"));
HtmlPage page = this.webClient.getPage("/sboot/vehicle.html");
assertThat(page.getBody().getTextContent()).isEqualTo("Honda Civic");
如果在类路径上有Spring Security,@WebMvcTest
也将扫描 WebSecurityConfigurer
bean。你可以使用Spring Security的测试支持,
而不是完全禁用此类测试的安全性。有关如何使用Spring Security的 MockMvc
支持的更多详细信息,请参见第80章
使用Spring Security测试方法部分。
要测试Spring WebFlux控制器是否按预期工作,可以使用 @WebFluxTest
注解。@WebFluxTest
自动配置Spring WebFlux基础设施并将扫描的
bean限制为 @Controller
,@ControllerAdvice
,@JsonComponent
,Converter
,GenericConverter
和 WebFluxConfigurer
。
使用 @WebFluxTest
注解时,不会扫描常规 @Component
bean。
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;
@RunWith(SpringRunner.class)
@WebFluxTest(UserVehicleController.class)
public class MyControllerTests {
@Autowired
private WebTestClient webClient;
@MockBean
private UserVehicleService userVehicleService;
@Test
public void testExample() throws Exception {
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.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@RunWith(SpringRunner.class)
@DataJpaTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public class ExampleNonTransactionalTests {
Data JPA测试还可以注入 TestEntityManager
bean,
它提供了专门为测试设计的标准JPA EntityManager
的替代方法。如果要在 @DataJpaTest
实例之外使用 TestEntityManager
,
还可以使用 @AutoConfigureTestEntityManager
注解。如果需要,还可以使用 JdbcTemplate
。
以下示例显示如何使用的 @DataJpaTest
注解:
import org.junit.*;
import org.junit.runner.*;
import org.springframework.boot.test.autoconfigure.orm.jpa.*;
import static org.assertj.core.api.Assertions.*;
@RunWith(SpringRunner.class)
@DataJpaTest
public class ExampleRepositoryTests {
@Autowired
private TestEntityManager entityManager;
@Autowired
private UserRepository repository;
@Test
public void testExample() throws Exception {
this.entityManager.persist(new User("sboot", "1234"));
User user = this.repository.findByUsername("sboot");
assertThat(user.getUsername()).isEqualTo("sboot");
assertThat(user.getVin()).isEqualTo("1234");
内存中嵌入式数据库通常适用于测试,因为它们速度快且不需要任何安装。但是,如果你更喜欢对真实数据库运行测试,
则可以使用 @AutoConfigureTestDatabase
注解配置,如以下示例所示:
@RunWith(SpringRunner.class)
@DataJpaTest
@AutoConfigureTestDatabase(replace=Replace.NONE)
public class ExampleRepositoryTests {
// ...
@JdbcTest
类似于 @DataJpaTest
,但适用于仅需要 DataSource
且不使用Spring Data JDBC的测试。
默认情况下,它配置内存中嵌入式数据库和 JdbcTemplate
。常规 @Component
bean不会被加载到 ApplicationContext
中。
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@RunWith(SpringRunner.class)
@JdbcTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public class ExampleNonTransactionalTests {
如果你希望测试针对真实数据库运行,则可以使用与 DataJpaTest
相同的方式使用 @AutoConfigureTestDatabase
注解。
(请参阅自动配置Data JPA测试部分)
@DataJdbcTest
类似于 @JdbcTest
,但适用于使用Spring Data JDBC存储库的测试。默认情况下,它配置内存中嵌入式数据库,
JdbcTemplate
和Spring Data JDBC存储库。常规 @Component
bean不会被加载到 ApplicationContext
中。
默认情况下,Data JDBC测试是事务性的,并在每次测试结束时回滚。有关更多详细信息,请参阅Spring框架参考指南中的 相关部分。
如果这不是你想要的,你可以像在JDBC示例中显示的那样为测试或整个类禁用事务管理。
如果你希望测试针对真实数据库运行,则可以使用与 DataJpaTest
相同的方式使用 @AutoConfigureTestDatabase
注解。
(请参阅自动配置Data JPA测试部分)
你可以像 @JdbcTest
一样使用 @JooqTest
但是它仅用于jOOQ相关的测试。由于jOOQ严重依赖于与数据库schema相对应的基于Java的schema,
因此会使用现有的 DataSource
。如果要将其替换为内存数据库,可以使用 @AutoConfigureTestDatabase
覆盖这些设置。
(有关在Spring Boot中使用jOOQ的更多信息,请参阅本章前面的 使用jOOQ)
常规 @Component
bean不会被加载到 ApplicationContext
中。
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.autoconfigure.jooq.JooqTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@JooqTest
public class ExampleJooqTests {
@Autowired
private DSLContext dslContext;
默认情况下,JOOQ测试是事务性的,并在每次测试结束时回滚。如果这不是你想要的,你可以像
在JDBC示例中显示的那样为测试或整个类禁用事务管理。
你可以使用 @DataMongoTest
来测试MongoDB应用程序。默认情况下,它配置内存中嵌入的MongoDB(如果可用),配置 MongoTemplate
,
扫描 @Document
类,以及配置Spring Data MongoDB存储库。常规 @Component
bean不会被加载到 ApplicationContext
中。
(有关将MongoDB与Spring Boot一起使用的更多信息,请参阅本章前面的 MongoDB部分)
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@DataMongoTest
public class ExampleDataMongoTests {
@Autowired
private MongoTemplate mongoTemplate;
内存中嵌入式MongoDB通常适用于测试,因为它速度快,不需要任何开发人员安装。但是,如果你更喜欢对真正的MongoDB服务器运行测试,
则应排除嵌入式MongoDB自动配置,如以下示例所示:
import org.junit.runner.RunWith;
import org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration;
import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@DataMongoTest(excludeAutoConfiguration = EmbeddedMongoAutoConfiguration.class)
public class ExampleDataMongoNonEmbeddedTests {
你可以使用 @DataNeo4jTest
来测试Neo4j应用程序。默认情况下,它使用内存中嵌入式Neo4j(如果嵌入式驱动程序可用),
扫描 @NodeEntity
类,并配置Spring Data Neo4j存储库。常规 @Component
bean不会被加载到 ApplicationContext
中。
(有关在Spring Boot中使用Neo4J的更多信息,请参阅本章前面的 使用Neo4j)
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.neo4j.DataNeo4jTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@DataNeo4jTest
public class ExampleDataNeo4jTests {
@Autowired
private YourRepository repository;
默认情况下,Data Neo4j测试是事务性的,并在每次测试结束时回滚。有关更多详细信息,请参阅Spring框架参考指南中的 相关部分。
如果这不是你想要的,你可以像下例所示为测试或整个类禁用事务管理。
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.autoconfigure.data.neo4j.DataNeo4jTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@RunWith(SpringRunner.class)
@DataNeo4jTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public class ExampleNonTransactionalTests {
你可以使用 @DataRedisTest
来测试Redis应用程序。默认情况下,它会扫描 @RedisHash
类并配置Spring Data Redis存储库。
常规 @Component
bean不会被加载到 ApplicationContext
中。
(有关将Redis与Spring Boot一起使用的更多信息,请参阅本章前面的 Redis部分)
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.redis.DataRedisTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@DataRedisTest
public class ExampleDataRedisTests {
@Autowired
private YourRepository repository;
你可以使用 @DataLdapTest
来测试LDAP应用程序。默认情况下,它配置内存中嵌入式LDAP(如果可用),配置 LdapTemplate
,
扫描 @Entry
类,以及配置Spring Data LDAP存储库。常规 @Component
bean不会被加载到 ApplicationContext
中。
(有关在Spring Boot中使用LDAP的更多信息,请参阅本章前面的 使用LDAP)
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.ldap.DataLdapTest;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@DataLdapTest
public class ExampleDataLdapTests {
@Autowired
private LdapTemplate ldapTemplate;
内存中嵌入式LDAP通常适用于测试,因为它速度快,不需要任何开发人员安装。
但是,如果你希望针对真实LDAP服务器运行测试,则应排除嵌入式LDAP自动配置,如以下示例所示:
import org.junit.runner.RunWith;
import org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration;
import org.springframework.boot.test.autoconfigure.data.ldap.DataLdapTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@DataLdapTest(excludeAutoConfiguration = EmbeddedLdapAutoConfiguration.class)
public class ExampleDataLdapNonEmbeddedTests {
@RunWith(SpringRunner.class)
@RestClientTest(RemoteVehicleDetailsService.class)
public class ExampleRestClientTest {
@Autowired
private RemoteVehicleDetailsService service;
@Autowired
private MockRestServiceServer server;
@Test
public void getVehicleDetailsWhenResultIsSuccessShouldReturnDetails()
throws Exception {
this.server.expect(requestTo("/greet/details"))
.andRespond(withSuccess("hello", MediaType.TEXT_PLAIN));
String greeting = this.service.callRestService();
assertThat(greeting).isEqualTo("hello");
你可以使用 @AutoConfigureRestDocs
注解在Mock MVC,REST Assured或WebTestClient的测试中使用
Spring REST Docs。它移除了Spring REST Docs中JUnit rule的需要。
@AutoConfigureRestDocs
可用于覆盖默认输出目录(如果你使用的是Maven,则为 target/generated-snippets
或
如果你使用的是Graven,则为 build/generated-snippets
)。它还可用于配置出现在任何已记录的URI中的host, scheme和port。
@AutoConfigureRestDocs
自定义 MockMvc
bean以使用Spring REST Docs。你可以使用 @Autowired
注入它,并在使用Mock MVC
和Spring REST Docs时在测试中使用它,如以下示例所示:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@RunWith(SpringRunner.class)
@WebMvcTest(UserController.class)
@AutoConfigureRestDocs
public class UserDocumentationTests {
@Autowired
private MockMvc mvc;
@Test
public void listUsers() throws Exception {
this.mvc.perform(get("/users").accept(MediaType.TEXT_PLAIN))
.andExpect(status().isOk())
.andDo(document("list-users"));
如果你需要更多对Spring REST Docs配置的控制,而不仅仅满足于 @AutoConfigureRestDocs
的属性,
则可以使用 RestDocsMockMvcConfigurationCustomizer
bean,如以下示例所示:
@TestConfiguration
static class CustomizationConfiguration
implements RestDocsMockMvcConfigurationCustomizer {
@Override
public void customize(MockMvcRestDocumentationConfigurer configurer) {
configurer.snippets().withTemplateFormat(TemplateFormats.markdown());
如果要对参数化输出目录使用Spring REST Docs支持,可以创建 RestDocumentationResultHandler
bean。
自动配置使用此结果处理程序调用 alwaysDo
,从而使每个 MockMvc
调用自动生成默认代码段。
以下示例显示何如定义 RestDocumentationResultHandler
:
@TestConfiguration
static class ResultHandlerConfiguration {
@Bean
public RestDocumentationResultHandler restDocumentation() {
return MockMvcRestDocumentation.document("{method-name}");
@AutoConfigureRestDocs` 生成一个 RequestSpecification
bean,预先配置为使用Spring REST Docs,可用于你的测试。
你可以使用 @Autowired
注入它并在测试中使用它,就像使用REST Assured和Spring REST Doc时一样,如下例所示:
import io.restassured.specification.RequestSpecification;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.test.context.junit4.SpringRunner;
import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.is;
import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.document;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureRestDocs
public class UserDocumentationTests {
@LocalServerPort
private int port;
@Autowired
private RequestSpecification documentationSpec;
@Test
public void listUsers() {
given(this.documentationSpec).filter(document("list-users")).when()
.port(this.port).get("/").then().assertThat().statusCode(is(200));
如果你需要对Spring REST Docs配置的更多控制,而不仅仅是 @AutoConfigureRestDocs
的属性,
则可以使用 RestDocsRestAssuredConfigurationCustomizer
bean,如以下示例所示:
@TestConfiguration
public static class CustomizationConfiguration
implements RestDocsRestAssuredConfigurationCustomizer {
@Override
public void customize(RestAssuredRestDocumentationConfigurer configurer) {
configurer.snippets().withTemplateFormat(TemplateFormats.markdown());
@RunWith(SpringRunner.class)
@JdbcTest
@ImportAutoConfiguration(IntegrationAutoConfiguration.class)
public class ExampleJdbcTests {
1.3.24. 使用Spock测试Spring Boot应用程序
如果你希望使用Spock测试Spring Boot应用程序,你应该将Spock spock-spring
模块的依赖项添加到应用程序的构建中。
spock-spring
集成Spring测试框架到Spock中。建议你使用Spock 1.2或更高版本,以便从Spock的Spring框架和Spring Boot
集成的许多改进中受益。有关更多详细信息,请参阅 Spock Spring模块的文档。
1.4.1. ConfigFileApplicationContextInitializer
ConfigFileApplicationContextInitializer
是一个 ApplicationContextInitializer
,你可以将其应用于测试以加载Spring Boot
application.properties
文件。当你不需要 @SpringBootTest
提供的全套功能时,可以使用它,如以下示例所示:
仅使用 ConfigFileApplicationContextInitializer
不支持 @Value("${…}")
注入。
它唯一的工作是确保将 application.properties
文件加载到Spring的环境中。
对于 @Value
支持,你需要另外配置 PropertySourcesPlaceholderConfigurer
或使用 @SpringBootTest
它会自动为你配置一个。
1.4.2. TestPropertyValues
TestPropertyValues
允许你快速向 ConfigurableEnvironment
或 ConfigurableApplicationContext
添加属性。
你可以使用 key=value
字符串调用它,如下所示:
TestPropertyValues.of("org=Spring", "name=Boot").applyTo(env);
1.4.3. OutputCapture
OutputCapture
是一个JUnit Rule
,可用于捕获 System.out
和 System.err
输出。你可以将捕获声明为 @Rule
,
然后使用 toString()
进行断言,如下所示:
import org.junit.Rule;
import org.junit.Test;
import org.springframework.boot.test.rule.OutputCapture;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
public class MyTest {
@Rule
public OutputCapture capture = new OutputCapture();
@Test
public void testName() throws Exception {
System.out.println("Hello World!");
assertThat(capture.toString(), containsString("World"));
TestRestTemplate
是Spring的 RestTemplate
的一种便利替代品,可用于集成测试。你可以获得一个vanilla模板或一个发送基本HTTP
身份验证(使用用户名和密码)的模板。在任何一种情况下,模板都以一种测试友好的方式运行,不会在服务器端错误上抛出异常。
建议(但不是强制性的)使用Apache HTTP Client(版本4.3.2或更高版本)。如果你在类路径上有这个,则 TestRestTemplate
通过适当地配置客户端来响应。如果你确实使用了Apache的HTTP客户端,则会启用一些额外的测试友好功能:
@Test
public void testRequest() throws Exception {
HttpHeaders headers = this.template.getForEntity(
"http://myhost.example.com/example", String.class).getHeaders();
assertThat(headers.getLocation()).hasHost("other.example.com");
或者,如果将 @SpringBootTest
注解与 WebEnvironment.RANDOM_PORT
或 WebEnvironment.DEFINED_PORT
一起使用,
则可以注入已完全配置的 TestRestTemplate
并开始使用它。如有必要,可以通过 RestTemplateBuilder
bean应用其他自定义。
任何未指定主机和端口的URL都会自动连接到嵌入式服务器,如以下示例所示:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class SampleWebClientTests {
@Autowired
private TestRestTemplate template;
@Test
public void testRequest() {
HttpHeaders headers = this.template.getForEntity("/example", String.class)
.getHeaders();
assertThat(headers.getLocation()).hasHost("other.example.com");
@TestConfiguration
static class Config {
@Bean
public RestTemplateBuilder restTemplateBuilder() {
return new RestTemplateBuilder().setConnectTimeout(Duration.ofSeconds(1))
.setReadTimeout(Duration.ofSeconds(1));