45.测试
Spring Boot提供了许多实用程序和注释来帮助您测试应用程序。测试支持由两个模块提供:spring-boot-test 包含核心
项, spring-boot-test-autoconfigure 支持测试的自动配置。
大多数开发人员使用 spring-boot-starter-test “Starter”,它导入Spring Boot测试模块以及JUnit,AssertJ,Hamcrest和许多其他有用
的库。
45.1测试范围依赖性
spring-boot-starter-test “Starter”(在 test scope 中)包含以下提供的库:
JUnit:单元测试Java应用程序的事实标准。
Spring测试和Spring Boot测试:Spring Boot应用程序的实用程序和集成测试支持。
AssertJ:一个流畅的断言库。
Hamcrest:匹配器对象库(也称为约束或谓词)。
Mockito:一个Java 模拟框架。
JSONassert:JSON的断言库。
JsonPath:JSON的XPath。
我们通常发现这些常用库在编写测试时很有用。如果这些库不适合您的需求,您可以添加自己的其他测试依赖项。
45.2测试Spring应用程序
依赖注入的一个主要优点是它应该使您的代码更容易进行单元测试。您可以使用 new 运算符实例化对象,甚至不涉及Spring。您还可以使用模拟
对象而不是真正的依赖项。
通常,您需要超越单元测试并开始集成测试(使用Spring ApplicationContext )。能够在不需要部署应用程序或需要连接到其他基础架构的
情况下执行集成测试非常有用。
Spring框架包括用于此类集成测试的专用测试模块。您可以直接向 org.springframework:spring-test 声明依赖关系,或使
用 spring-boot-starter-test “Starter”将其传递给它。
如果您之前未使用过 spring-test 模块,则应首先阅读Spring框架参考文档的 相关部分。
45.3测试Spring Boot应用程序
Spring Boot应用程序是Spring ApplicationContext ,因此除了通常使用vanilla Spring上下文所做的测试之外,没有什么特别的要做。
仅当您使用 SpringApplication 创建外部属性,日志记录和Spring Boot的其他功能时,才会默认安装在上下文中。
Spring Boot提供了 @SpringBootTest 注释,当您需要Spring引导功能时,可以将其用作标准 spring-test @ContextConfiguration 注释
的替代。注释的工作原理是 通过 SpringApplication 创建测试中使用的 ApplicationContext 。除了 @SpringBootTest 之外,还提供了许多
其他注释来 测试应用程序的更具体的切片。
如果您使用的是JUnit 4,请不要忘记在测试中添加 @RunWith(SpringRunner.class) ,否则注释将被忽略。如果您正在使用
JUnit 5,则无需将等效的 @ExtendWith(SpringExtension) 添加为 @SpringBootTest ,而其他 @…Test 注释已经使用它进行注
释。
默认情况下, @SpringBootTest 将无法启动服务器。您可以使用 @SpringBootTest 的 webEnvironment 属性来进一步优化测试的运行方式:
MOCK (默认):加载网络 ApplicationContext 并提供模拟网络环境。使用此批注时,不会启动嵌入式服务器。如果您的类路径上没有
Web环境,则此模式将透明地回退到创建常规非Web ApplicationContext 。它可以与 @AutoConfigureMockMvc
或 @AutoConfigureWebTestClient 一起用于基于模拟的Web应用程序测试。
RANDOM_PORT :加载 WebServerApplicationContext 并提供真实的网络环境。嵌入式服务器启动并在随机端口上侦听。
DEFINED_PORT :加载 WebServerApplicationContext 并提供真实的网络环境。嵌入式服务器启动并侦听定义的端口(来自您
的 application.properties )或默认端口 8080 。
NONE :使用 SpringApplication 加载 ApplicationContext 但不提供 任何网络环境(模拟或其他)。
如果您的测试是 @Transactional ,则默认情况下会在每个测试方法的末尾回滚事务。但是,当使用 RANDOM_PORT
或 DEFINED_PORT 的这种安排隐式地提供真正的servlet环境时,HTTP客户端和服务器在单独的线程中运行,因此在单独的事务中
运行。在这种情况下,在服务器上启动的任何事务都不会回滚。
如果您的应用程序使用不同的管理服务器端口, @SpringBootTest 和 webEnvironment = WebEnvironment.RANDOM_PORT 也将
在单独的随机端口上启动管理服务器。
45.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 { ... }
45.3.2检测测试配置
如果您熟悉Spring测试框架,则可能习惯使用 @ContextConfiguration(classes=… ) 来指定要加载的Spring @Configuration 。或者,您可
能经常在测试中使用嵌套的 @Configuration 类。
在测试Spring Boot应用程序时,通常不需要这样做。只要您没有明确定义一个,Spring Boot的 @*Test 注释就会自动搜索您的主要配置。
搜索算法从包含测试的包开始工作,直到找到使用 @SpringBootApplication 或 @SpringBootConfiguration 注释的类。只要您以合理的方式
构建代码,通常就会找到主要配置。
如果使用 测试批注来测试应用程序的更具体的片段,则应避免在main方法的应用程序类中添加特定于特定区域的配置设置 。
@SpringBootApplication 的基础组件扫描配置定义了排除过滤器,用于确保切片按预期工作。如果您
在 @SpringBootApplication - 带注释的类上使用明确的 @ComponentScan 指令,请注意这些过滤器将被禁用。如果您正在使用
切片,则应再次定义它们。
如果要自定义主要配置,可以使用嵌套的 @TestConfiguration 类。与嵌套的 @Configuration 类不同,它将用于代替应用程序的主要配置,
除了应用程序的主要配置之外,还使用嵌套的 @TestConfiguration 类。
Spring的测试框架在测试之间缓存应用程序上下文。因此,只要您的测试共享相同的配置(无论如何发现),加载上下文的潜在耗
时过程只发生一次。
45.3.3排除测试配置
如果您的应用程序使用组件扫描(例如,如果您使用 @SpringBootApplication 或 @ComponentScan ),您可能会发现仅为特定测试创建的顶
级配置类会意外地在任何地方进行检索。
如前所述, @TestConfiguration 可用于测试的内部类以自定义主要配置。前面所看到的,1941年{/}可以在一个内部类的测试的用于定制的主
配置。当放置在顶级类时, @TestConfiguration 表示不应通过扫描拾取 src/test/java 中的类。然后,您可以在需要的位置显式导入该类,
如以下示例所示:
@RunWith(SpringRunner.class)
@SpringBootTest
@Import(MyTestsConfiguration.class)
public class MyTests {
@Test
public void exampleTest() {
...
}
}
如果您直接使用 @ComponentScan (即不通过 @SpringBootApplication ),则需要使用 TypeExcludeFilter 注册。