Test Spring Boot提供了许多实用程序和注释来帮助您测试应用程序。测试支持由两个模块提供:spring-boot-test包含核心项,并spring-boot-test-autoconfigure支持测试的自动配置。
大多数开发人员使用spring-boot-starter-test启动器,它导入Spring Boot测试模块以及JUnit,AssertJ,Hamcrest和许多其他有用的库。
测试范围依赖性 在spring-boot-starter-test启动器中(test scope)包含以下提供的库:
我们通常发现这些常用库在编写测试时很有用。如果这些库不符合您的需求,您可以添加自己的其他测试依赖项。
测试Spring应用程序 依赖注入的一个主要优点是它应该使您的代码更容易进行单元测试。您可以使用new运算符实例化对象,甚至不涉及Spring。您还可以使用模拟对象 而不是真正的依赖项。
通常,您需要超越单元测试并开始集成测试(使用Spring ApplicationContext)。能够在不需要部署应用程序或需要连接到其他基础架构的情况下执行集成测试非常有用。
Spring Framework包含一个用于此类集成测试的专用测试模块。您可以直接声明依赖关系org.springframework:spring-test或使用spring-boot-starter-test“Starter”来传递它。
如果您之前没有使用过该spring-test模块,那么首先应阅读Spring Framework参考文档的 相关部分 。
测试Spring Boot应用程序 Spring Boot应用程序是一个Spring ApplicationContext,所以没有什么特别的东西可以用来测试它超出你通常使用的Spring语境。
只有在您SpringApplication创建Spring Boot的外部属性,日志记录和其他功能时,默认情况下才会在上下文中安装它们。
Spring Boot提供了一个@SpringBootTest注释,spring-test @ContextConfiguration当您需要Spring Boot功能时,它可以用作标准注释的替代方法。注释的工作原理是通过 创建 ApplicationContext测试中使用的SpringApplication 。除了 @SpringBootTest提供许多其他注释之外,还提供了用于 测试 应用程序的更具体的切片 。
如果您使用的是JUnit 4,请不要忘记添加@RunWith(SpringRunner.class)到测试中,否则注释将被忽略。如果您使用的是JUnit 5,则无需添加等效项@ExtendWith(SpringExtension),@SpringBootTest并且其他@…Test注释已经使用它进行注释。
默认情况下,@SpringBootTest不会启动服务器。您可以使用该webEnvironment 属性@SpringBootTest进一步优化测试的运行方式:
MOCK(默认):加载Web ApplicationContext并提供模拟Web环境。使用此批注时,不会启动嵌入式服务器。如果类路径上没有Web环境,则此模式将透明地回退到创建常规非Web ApplicationContext。它可以与Web应用程序一起使用 @AutoConfigureMockMvc或@AutoConfigureWebTestClient 用于基于模拟的Web应用程序测试。
RANDOM_PORT:加载a WebServerApplicationContext并提供真实的Web环境。嵌入式服务器启动并在随机端口上侦听。
DEFINED_PORT:加载a WebServerApplicationContext并提供真实的Web环境。嵌入式服务器启动并侦听定义的端口(来自您的application.properties)或默认端口8080。
NONE:ApplicationContext通过使用SpringApplication但不提供 任何 Web环境(模拟或其他)来加载。
如果您的测试是@Transactional,则默认情况下会在每个测试方法结束时回滚事务。但是,当使用这种安排RANDOM_PORT或者 DEFINED_PORT隐式地提供真实的servlet环境时,HTTP客户端和服务器在不同的线程中运行,因此在单独的事务中运行。在这种情况下,在服务器上启动的任何事务都不会回滚。
@SpringBootTest`webEnvironment = WebEnvironment.RANDOM_PORT`如果您的应用程序使用管理服务器的不同端口,则还将在单独的随机端口上启动管理服务器。
检测Web应用程序类型 如果Spring MVC可用,则配置基于MVC的常规应用程序上下文。如果您只有Spring WebFlux,我们会检测到并配置基于WebFlux的应用程序上下文。
如果两者都存在,则Spring MVC优先。如果要在此方案中测试响应式Web应用程序,则必须设置该spring.main.web-application-type 属性:
1 2 3 @RunWith (SpringRunner.class)@SpringBootTest (properties = "spring.main.web-application-type=reactive" )public class MyWebFluxTests { ... }
检测测试配置 如果您熟悉Spring Test Framework,则可能习惯使用 @ContextConfiguration(classes=…)以指定@Configuration要加载的Spring 。或者,您可能经常@Configuration在测试中使用嵌套类。
在测试Spring Boot应用程序时,通常不需要这样做。@*Test 只要您没有明确定义,Spring Boot的注释就会自动搜索您的主要配置。
搜索算法从包含测试的包开始工作,直到找到用@SpringBootApplicationor 注释的类@SpringBootConfiguration。只要您以合理的方式构建代码 ,通常就会找到主要配置。
如果使用 测试批注来测试应用程序的更具体的片段 ,则应避免在main方法的应用程序类中 添加特定于特定区域的配置设置 。
@SpringBootApplication定义的基础组件扫描配置排除了用于确保切片按预期工作的过滤器。如果您@ComponentScan在已@SpringBootApplication注释的类上使用显式 指令,请注意将禁用这些过滤器。如果您正在使用切片,则应再次定义它们。
如果要自定义主要配置,可以使用嵌套 @TestConfiguration类。与嵌套@Configuration类不同,嵌套类将用于代替应用程序的主要配置,@TestConfiguration除了应用程序的主要配置之外,还使用嵌套类。
Spring的测试框架在测试之间缓存应用程序上下文。因此,只要您的测试共享相同的配置(无论如何发现),加载上下文的潜在耗时过程只发生一次。
排除测试配置 如果您的应用程序使用组件扫描(例如,如果您使用 @SpringBootApplication或@ComponentScan),您可能会发现仅为特定测试创建的顶级配置类会意外地在任何地方被捕获。
正如我们之前所见 ,@TestConfiguration可以在测试的内部类上使用来自定义主要配置。放置在顶级类时,@TestConfiguration表示src/test/java不应通过扫描拾取类。然后,您可以在需要的位置显式导入该类,如以下示例所示:
1 2 3 4 5 6 7 8 9 10 @RunWith (SpringRunner.class)@SpringBootTest @Import (MyTestsConfiguration.class)public class MyTests { @Test public void exampleTest () { ... } }
如果您直接使用@ComponentScan(即不通过 @SpringBootApplication),则需要注册TypeExcludeFilter。有关详细信息,请参阅 Javadoc 。
使用模拟环境进行测试 默认情况下,@SpringBootTest不启动服务器。如果您要针对此模拟环境测试Web端点,则可以另外进行配置 MockMvc ,如以下示例所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import org.junit.Test;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" )); } }
如果你想只专注于网络层,而不是开始一个完整的 ApplicationContext,可以考虑 使用 @WebMvcTest替代 。
或者,您可以配置一个 WebTestClient ,如以下示例所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import org.junit.Test;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" ); } }
使用正在运行的服务器进行测试 如果您需要启动一个完整运行的服务器,我们建议您使用随机端口。如果使用@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT),每次测试运行时都会随机选取一个可用端口。
该@LocalServerPort注释可用于 注射使用的实际端口 到您的测试。为了方便起见,测试,需要做出REST调用启动的服务器可另外@Autowire一个WebTestClient ,它解析为正在运行的服务器相对链接,并附带了用于验证响应的专用API,如下面的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 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工具:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 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" ); } }
使用JMX 当测试上下文框架缓存上下文时,默认情况下禁用JMX以防止相同的组件在同一域上注册。如果此类测试需要访问 MBeanServer,请考虑将其标记为脏:
1 2 3 4 5 6 7 8 9 10 11 12 13 @RunWith (SpringRunner.class)@SpringBootTest (properties = "spring.jmx.enabled=true" )@DirtiesContext public class SampleJmxTests { @Autowired private MBeanServer mBeanServer; @Test public void exampleTest () { } }
Mocking and Spying Beans 运行测试时,有时需要在应用程序上下文中模拟某些组件。例如,您可能拥有在开发期间不可用的某些远程服务的外观。当您想要模拟在真实环境中难以触发的故障时,模拟也很有用。
Spring Boot包含一个@MockBean注释,可用于为您内部的bean定义Mockito模拟ApplicationContext。您可以使用批注添加新bean或替换单个现有bean定义。注释可以直接用于测试类,测试中的字段,或@Configuration类和字段。在字段上使用时,也会注入创建的模拟的实例。每种测试方法后,模拟豆都会自动重置。
如果您的测试使用Spring Boot的测试注释之一(例如@SpringBootTest),则会自动启用此功能。要以不同的排列方式使用此功能,必须显式添加侦听器,如以下示例所示:
1 @TestExecutionListeners (MockitoTestExecutionListener.class)
以下示例使用RemoteService模拟实现替换现有bean:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 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 () { given(this .remoteService.someCall()).willReturn("mock" ); String reverse = reverser.reverseSomeCall(); assertThat(reverse).isEqualTo("kcom" ); } }
此外,您可以使用@SpyBeanMockito来包装任何现有的bean spy。有关详细信息,请参阅Javadoc 。
虽然Spring的测试框架在测试之间缓存应用程序上下文并重用共享相同配置的测试的上下文,但是使用@MockBean或@SpyBean 影响缓存键,这很可能会增加上下文的数量。
如果您使用通过名称引用参数的方法@SpyBean来监视bean,则@Cacheable必须使用编译应用程序-parameters。这确保了一旦bean被监视,参数名称可用于缓存基础结构。
自动配置的测试 Spring Boot的自动配置系统适用于应用程序,但有时对于测试来说有点太多了。通常有助于仅加载测试应用程序“切片”所需的配置部分。例如,您可能希望测试Spring MVC控制器是否正确映射URL,并且您不希望在这些测试中涉及数据库调用,或者您可能想要测试JPA实体,并且您对Web层不感兴趣测试运行。
该spring-boot-test-autoconfigure模块包括许多可用于自动配置这种“切片”的注释。它们中的每一个都以类似的方式工作,提供一个@…Test注释,用于加载可用于自定义自动配置设置的ApplicationContext一个或多个@AutoConfigure…注释。
每个切片将组件扫描限制为适当的组件,并加载一组非常有限的自动配置类。如果您需要排除其中一个,大多数@…Test注释都会提供一个excludeAutoConfiguration属性。或者,您可以使用@ImportAutoConfiguration#exclude。
@Test不支持在一次测试中使用多个注释包括多个“切片” 。如果您需要多个“切片”,请选择其中一个@…Test注释并@AutoConfigure…手动包含其他“切片” 的注释。
也可以使用@AutoConfigure…带有标准 @SpringBootTest注释的注释。如果您对“切片”应用程序不感兴趣但想要一些自动配置的测试bean,则可以使用此组合。
自动配置的JSON测试 要测试该对象JSON序列化和反序列化是否按预期工作,您可以使用@JsonTest注释。@JsonTest自动配置可用的受支持JSON映射器,它可以是以下库之一:
JacksonObjectMapper,任何@JsonComponentbeans和JacksonModuleS
Gson
Jsonb
@JsonTest可以 在附录中找到 启用的自动配置列表。
如果需要配置自动配置的元素,可以使用 @AutoConfigureJsonTesters注释。
Spring Boot包括基于AssertJ的助手,它们与JSONAssert和JsonPath库一起使用,以检查JSON是否按预期显示。的JacksonTester,GsonTester,JsonbTester,和BasicJsonTester类可以分别用于杰克逊,GSON,Jsonb,和字符串。测试类上的任何辅助字段都可以@Autowired在使用时使用@JsonTest。以下示例显示了Jackson的测试类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 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" ); assertThat(this .json.write(details)).isEqualToJson("expected.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" ); } }
JSON帮助程序类也可以直接在标准单元测试中使用。为此,如果不使用,请在initFields方法中调用帮助程序的@Before方法 @JsonTest。
自动配置的Spring MVC测试 要测试Spring MVC控制器是否按预期工作,请使用@WebMvcTest 注释。@WebMvcTest自动配置Spring MVC的基础设施和限制扫描豆@Controller,@ControllerAdvice,@JsonComponent,Converter, GenericConverter,Filter,WebMvcConfigurer,和HandlerMethodArgumentResolver。@Component使用此批注时不会扫描常规bean。
@WebMvcTest可以 在附录中找到 启用的自动配置设置列表。
如果需要注册额外的组件,例如Jackson Module,则可以@Import在测试中使用其他配置类。
通常,@WebMvcTest仅限于单个控制器,并与其结合使用 @MockBean,为所需的协作者提供模拟实现。
@WebMvcTest还自动配置MockMvc。Mock MVC提供了一种快速测试MVC控制器的强大方法,无需启动完整的HTTP服务器。
您还可以通过使用注释来MockMvc非自动配置@WebMvcTest(例如 @SpringBootTest)@AutoConfigureMockMvc。以下示例使用MockMvc:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 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" )); } }
如果需要配置自动配置的元素(例如,应该应用servlet过滤器时),则可以使用@AutoConfigureMockMvc 注释中的属性。
如果您使用HtmlUnit或Selenium,则自动配置还提供HTMLUnit WebClient bean和/或WebDriverbean。以下示例使用HtmlUnit:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import com.gargoylesoftware.htmlunit.*;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 Boot将WebDriverbean放在一个特殊的“范围”中,以确保驱动程序在每次测试后退出并注入新实例。如果您不想要此行为,可以添加@Scope("singleton")到您的WebDriver @Bean 定义中。
webDriverSpring Boot创建的范围将替换任何用户定义的同名范围。如果您定义自己的webDriver范围,您可能会发现它在您使用时停止工作@WebMvcTest。
如果在类路径上有Spring Security,@WebMvcTest则还会扫描WebSecurityConfigurer bean。您可以使用Spring Security的测试支持,而不是完全禁用此类测试的安全性。有关如何使用Spring Security MockMvc支持的更多详细信息,请参见第80章“ 使用Spring Security测试 方法”部分。
有时编写Spring MVC测试是不够的; Spring Boot可以帮助您使用实际服务器 运行 完整的端到端测试 。
自动配置的Spring WebFlux测试 要测试Spring WebFlux 控制器是否按预期工作,您可以使用@WebFluxTest注释。@WebFluxTest 自动配置春季WebFlux基础设施和限制扫描豆@Controller,@ControllerAdvice,@JsonComponent,Converter,GenericConverter,和 WebFluxConfigurer。 使用注释@Component时不会扫描常规bean @WebFluxTest。
@WebFluxTest可以 在附录中找到 启用的自动配置列表。
如果需要注册额外的组件,例如Jackson Module,则可以@Import在测试中导入其他配置类。
通常,@WebFluxTest仅限于单个控制器并与@MockBean注释结合使用, 以便为所需的协作者提供模拟实现。
@WebFluxTest还有自动配置 WebTestClient ,这提供了一种快速测试WebFlux控制器的强大方法,无需启动完整的HTTP服务器。
您还可以通过使用注释来WebTestClient非自动配置@WebFluxTest(例如 @SpringBootTest)@AutoConfigureWebTestClient。以下示例显示了使用both @WebFluxTest和a的类WebTestClient:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 import org.junit.Test;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" ); } }
此设置仅由WebFlux应用程序支持,因为WebTestClient在模拟的Web应用程序中使用仅适用于WebFlux。
@WebFluxTest无法检测通过功能Web框架注册的路由。要RouterFunction在上下文中测试bean,请考虑RouterFunction 通过@Import或使用自己导入@SpringBootTest。
有时编写Spring WebFlux测试是不够的; Spring Boot可以帮助您使用实际服务器 运行 完整的端到端测试 。
自动配置的数据JPA测试 您可以使用@DataJpaTest注释来测试JPA应用程序。默认情况下,它配置内存中的嵌入式数据库,扫描@Entity类并配置Spring Data JPA存储库。常规@Componentbean没有加载到 ApplicationContext。
@DataJpaTest可以 在附录中找到 启用的自动配置设置列表。
默认情况下,数据JPA测试是事务性的,并在每次测试结束时回滚。有关 更多详细信息,请参阅Spring Framework Reference Documentation中的相关部分 。如果这不是您想要的,您可以为测试或整个类禁用事务管理,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 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 {}
数据JPA测试也可以注入一个 TestEntityManager bean,它提供了EntityManager专门为测试设计的标准JPA的替代方法。如果要TestEntityManager在@DataJpaTest实例外部 使用,也可以使用@AutoConfigureTestEntityManager 注释。JdbcTemplate如果您需要,也可以使用A. 以下示例显示@DataJpaTest正在使用的注释:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 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注释,如以下示例所示:
1 2 3 4 5 6 @RunWith (SpringRunner.class)@DataJpaTest @AutoConfigureTestDatabase (replace=Replace.NONE)public class ExampleRepositoryTests { }
自动配置的JDBC测试 @JdbcTest类似于@DataJpaTest但仅适用于仅需要 DataSource并且不使用Spring Data JDBC的测试。默认情况下,它配置内存中的嵌入式数据库和JdbcTemplate。常规@Componentbean没有加载到ApplicationContext。
@JdbcTest可以 在附录中找到 启用的自动配置列表。
默认情况下,JDBC测试是事务性的,并在每次测试结束时回滚。有关更多详细信息,请参阅Spring Framework Reference Documentation中的 相关部分 。如果这不是您想要的,您可以禁用测试或整个类的事务管理,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 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 {}
如果您希望测试针对真实数据库运行,则可以使用与@AutoConfigureTestDatabase注释相同的方式使用 注释DataJpaTest。(参见“ 第46.3.12节 ” ,”自动配置的数据JPA测试 “)
自动配置的数据JDBC测试 @DataJdbcTest类似于@JdbcTest但是适用于使用Spring Data JDBC存储库的测试。默认情况下,它配置内存中的嵌入式数据库,a JdbcTemplate和Spring Data JDBC存储库。常规@Componentbean没有加载到ApplicationContext。
@DataJdbcTest可以 在附录中找到 启用的自动配置列表。
默认情况下,数据JDBC测试是事务性的,并在每次测试结束时回滚。有关 更多详细信息,请参阅Spring Framework Reference Documentation中的相关部分 。如果这不是您想要的,您可以禁用测试或整个测试类的事务管理,如 JDBC示例中所示 。
如果您希望测试针对真实数据库运行,则可以使用与@AutoConfigureTestDatabase注释相同的方式使用 注释DataJpaTest。(参见“ 第46.3.12节 ” ,”自动配置的数据JPA测试 “)
自动配置的jOOQ测试 您可以使用@JooqTest与@JdbcTestjOOQ相关的测试类似的方式。由于jOOQ严重依赖于与数据库模式对应的基于Java的模式,因此使用现有模式DataSource。如果要将其替换为内存数据库,可以使用@AutoConfigureTestDatabase覆盖这些设置。(有关在Spring Boot中使用jOOQ的更多信息,请参阅本章前面的“ 第31.6节 ” ,“使用jOOQ” 。)常规 @Componentbean不会加载到ApplicationContext。
@JooqTest可以 在附录中找到 启用的自动配置列表。
@JooqTest配置一个DSLContext。常规@Componentbean没有加载到 ApplicationContext。以下示例显示@JooqTest正在使用的注释:
1 2 3 4 5 6 7 8 9 10 11 12 13 import org.jooq.DSLContext;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示例中所示 。
自动配置的数据MongoDB测试 您可以使用它@DataMongoTest来测试MongoDB应用程序。默认情况下,它配置内存中嵌入的MongoDB(如果可用),配置MongoTemplate,扫描 @Document类以及配置Spring Data MongoDB存储库。常规 @Componentbean没有加载到ApplicationContext。(有关将MongoDB与Spring Boot一起使用的更多信息,请参阅本章前面的“ 第32.2节”,“MongoDB” 。)
@DataMongoTest可以 在附录中找到 启用的自动配置设置列表。
以下类显示@DataMongoTest正在使用的注释:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 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自动配置,如以下示例所示:
1 2 3 4 5 6 7 8 9 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 {}
自动配置的数据Neo4j测试 您可以使用它@DataNeo4jTest来测试Neo4j应用程序。默认情况下,它使用内存中嵌入式Neo4j(如果嵌入式驱动程序可用),扫描@NodeEntity类并配置Spring Data Neo4j存储库。常规@Componentbean没有加载到ApplicationContext。(有关使用带有Spring Boot的Neo4J的更多信息,请参阅本章前面的“ 第32.3节”,“Neo4j” 。)
@DataNeo4jTest可以 在附录中找到 启用的自动配置设置列表。
以下示例显示了在Spring Boot中使用Neo4J测试的典型设置:
1 2 3 4 5 6 7 8 9 10 11 12 13 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)@DataNeo 4jTestpublic class ExampleDataNeo4jTests { @Autowired private YourRepository repository; }
默认情况下,Data Neo4j测试是事务性的,并在每次测试结束时回滚。有关更多详细信息,请参阅Spring Framework Reference Documentation中的相关部分 。如果这不是您想要的,您可以禁用测试或整个类的事务管理,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 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)@DataNeo 4jTest@Transactional (propagation = Propagation.NOT_SUPPORTED)public class ExampleNonTransactionalTests {}
自动配置的数据Redis测试 您可以使用它@DataRedisTest来测试Redis应用程序。默认情况下,它会扫描 @RedisHash类并配置Spring Data Redis存储库。常规@Component bean没有加载到ApplicationContext。(有关使用带有Spring Boot的Redis的更多信息,请参阅本章前面的“ 第32.1节”,“Redis” 。)
@DataRedisTest可以 在附录中找到 启用的自动配置设置列表。
以下示例显示@DataRedisTest正在使用的注释:
1 2 3 4 5 6 7 8 9 10 11 12 13 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; }
自动配置的数据LDAP测试 您可以使用它@DataLdapTest来测试LDAP应用程序。默认情况下,它配置内存中嵌入式LDAP(如果可用),配置LdapTemplate,扫描@Entry 类以及配置Spring Data LDAP存储库。常规@Componentbean没有加载到ApplicationContext。(有关在Spring Boot中使用LDAP的更多信息,请参阅本章前面的“ 第32.9节”,“LDAP” 。)
@DataLdapTest可以 在附录中找到 启用的自动配置设置列表。
以下示例显示@DataLdapTest正在使用的注释:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 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自动配置,如以下示例所示:
1 2 3 4 5 6 7 8 9 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 {}
自动配置的REST客户端 您可以使用@RestClientTest注释来测试REST客户端。默认情况下,它会自动配置Jackson,GSON和Jsonb支持,配置RestTemplateBuilder并添加支持MockRestServiceServer。常规@Componentbean没有加载到ApplicationContext。
@RestClientTest可以在附录中找到 启用的自动配置设置列表。
应使用valueor components属性指定要测试的特定bean @RestClientTest,如以下示例所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @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" ); } }
自动配置的Spring REST Docs测试 您可以使用@AutoConfigureRestDocs注释在Mock MVC,REST Assured或WebTestClient的测试中使用Spring REST Docs 。它消除了对Spring REST Docs中JUnit规则的需求。
@AutoConfigureRestDocs可用于覆盖默认输出目录(target/generated-snippets如果您使用的是Maven,或者build/generated-snippets如果您使用的是Gradle)。它还可用于配置出现在任何已记录的URI中的主机,方案和端口。
使用Mock MVC自动配置Spring REST Docs测试 @AutoConfigureRestDocs自定义MockMvcbean以使用Spring REST Docs。您可以@Autowired像在通常使用Mock MVC和Spring REST Docs时那样在测试中使用它来注入它,如以下示例所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 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可以使用 RestDocsMockMvcConfigurationCustomizerbean,如以下示例所示:
1 2 3 4 5 6 7 8 9 @TestConfiguration static class CustomizationConfiguration implements RestDocsMockMvcConfigurationCustomizer { @Override public void customize (MockMvcRestDocumentationConfigurer configurer) { configurer.snippets().withTemplateFormat(TemplateFormats.markdown()); } }
如果要对参数化输出目录使用Spring REST Docs支持,可以创建RestDocumentationResultHandlerbean。自动配置alwaysDo使用此结果处理程序调用 ,从而使每个MockMvc调用自动生成默认代码段。以下示例显示了 RestDocumentationResultHandler正在定义的内容:
1 2 3 4 5 6 7 8 @TestConfiguration static class ResultHandlerConfiguration { @Bean public RestDocumentationResultHandler restDocumentation () { return MockMvcRestDocumentation.document("{method-name}" ); } }
使用REST Assured自动配置Spring REST Docs测试 @AutoConfigureRestDocs制作一个RequestSpecification预先配置为使用Spring REST Docs 的bean,可用于您的测试。您可以@Autowired像在通常使用REST Assured和Spring REST Doc时那样在测试中使用它来注入它,如以下示例所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 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,如以下示例所示:
1 2 3 4 5 6 7 8 9 @TestConfiguration public static class CustomizationConfiguration implements RestDocsRestAssuredConfigurationCustomizer { @Override public void customize (RestAssuredRestDocumentationConfigurer configurer) { configurer.snippets().withTemplateFormat(TemplateFormats.markdown()); } }
附加自动配置和切片 每个切片提供一个或多个@AutoConfigure…注释,即定义应作为切片的一部分包括的自动配置。可以通过创建自定义@AutoConfigure…注释或仅通过添加@ImportAutoConfiguration到测试来添加其他自动配置,如以下示例所示:
1 2 3 4 5 @RunWith (SpringRunner.class)@JdbcTest @ImportAutoConfiguration (IntegrationAutoConfiguration.class)public class ExampleJdbcTests {}
确保不使用常规@Import注释来导入自动配置,因为Spring Boot会以特定方式处理它们。
用户配置和切片 如果以合理的方式构造代码 ,@SpringBootApplication则默认情况下 会将您的 类 用作 测试的配置。
然后,重要的是不要使用特定于其功能的特定区域的配置设置来丢弃应用程序的主类。
假设您正在使用Spring Batch并依赖于它的自动配置。您可以@SpringBootApplication按如下方式定义:
1 2 3 @SpringBootApplication @EnableBatchProcessing public class SampleApplication { ... }
因为此类是测试的源配置,所以任何切片测试实际上都会尝试启动Spring Batch,这绝对不是您想要做的。建议的方法是将特定于区域的配置移动到与@Configuration应用程序相同级别的单独类中,如以下示例所示:
1 2 3 @Configuration @EnableBatchProcessing public class BatchConfiguration { ... }
根据应用程序的复杂程度,您可能只有一个 @Configuration类用于自定义,或者每个域区域有一个类。后一种方法允许您在必要时使用@Import注释在其中一个测试中启用它。
混淆的另一个原因是类路径扫描。假设您以合理的方式构建代码,则需要扫描其他包。您的应用程序可能类似于以下代码:
1 2 3 @SpringBootApplication @ComponentScan ({ "com.example.app" , "org.acme.another" })public class SampleApplication { ... }
这样做会有效地覆盖默认组件扫描指令,并且无论您选择哪个切片,都会扫描这两个包。例如, @DataJpaTest似乎突然扫描了应用程序的组件和用户配置。同样,将自定义指令移动到单独的类是解决此问题的好方法。
如果这不是您的选项,您可以@SpringBootConfiguration 在测试的层次结构中创建一个位置,以便使用它。或者,您可以为测试指定源,这会禁用查找默认源的行为。
使用Spock测试Spring Boot应用程序 如果您希望使用Spock来测试Spring Boot应用程序,您应该将Spock spock-spring模块的依赖项添加到应用程序的构建中。spock-spring将Spring的测试框架集成到Spock中。建议您使用Spock 1.2或更高版本从Spock的Spring Framework和Spring Boot集成的许多改进中受益。有关更多详细信息,请参阅Spock Spring模块的文档 。
测试应用程序 在测试应用程序时通常有用的一些测试实用程序类是作为其一部分打包的spring-boot。
ConfigFileApplicationContextInitializer ConfigFileApplicationContextInitializer是一个ApplicationContextInitializer可以应用于测试以加载Spring Boot application.properties文件的。当您不需要提供的全部功能时,可以使用它@SpringBootTest,如以下示例所示:
1 2 @ContextConfiguration (classes = Config.class, initializers = ConfigFileApplicationContextInitializer.class)
ConfigFileApplicationContextInitializer单独使用不提供@Value("${…}")注射支持 。它唯一的工作是确保将application.properties文件加载到Spring中Environment。要获得@Value支持,您需要另外配置PropertySourcesPlaceholderConfigurer或使用@SpringBootTest,为您自动配置一个。
TestPropertyValues TestPropertyValues让您快速添加属性 ConfigurableEnvironment或ConfigurableApplicationContext。您可以使用key=value字符串调用它 ,如下所示:
1 TestPropertyValues.of("org=Spring" , "name=Boot" ).applyTo(env);
OutputCapture OutputCapture是一个Rule可以用来捕获System.out和 System.err输出的JUnit 。您可以将捕获声明为a @Rule然后toString() 用于断言,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 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 Framework 5.0提供了一个WebTestClient适用于 WebFlux集成测试 以及 WebFlux和MVC端到端测试的新功能 。它提供了一个流畅的断言API,不像TestRestTemplate。
TestRestTemplate是Spring的便捷替代品,RestTemplate在集成测试中很有用。您可以获得一个vanilla模板或一个发送基本HTTP身份验证(使用用户名和密码)的模板。在任何一种情况下,模板都以一种测试友好的方式运行,不会在服务器端错误上抛出异常。建议(但不是强制性的)使用Apache HTTP Client(版本4.3.2或更高版本)。如果您在类路径中有这个,则TestRestTemplate通过适当地配置客户端来响应。如果您确实使用Apache的HTTP客户端,则启用一些其他测试友好功能:
不遵循重定向(因此您可以断言响应位置)。
Cookie被忽略(因此模板是无状态的)。
TestRestTemplate 可以直接在集成测试中实例化,如以下示例所示:
1 2 3 4 5 6 7 8 9 10 11 12 public class MyTest { private TestRestTemplate template = new TestRestTemplate(); @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注释 ,则可以注入完全配置并开始使用它。如有必要,可以通过bean 应用其他自定义。任何未指定主机和端口的URL都会自动连接到嵌入式服务器,WebEnvironment.RANDOM_PORT WebEnvironment.DEFINED_PORT TestRestTemplate RestTemplateBuilder如以下示例所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 @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 )); } } }