Spring为了避免的繁琐难懂的xml配置,引入大量annotation进行系统配置,确实减轻了配置工作量。由此,理解这些annotation变得尤为重要,一定程度上讲,对Spring Boot Test的使用,就是对其相关annotation的使用。
掌握这些annotation(及部分关联的类),可以从注解功能分类,相互之间的搭配组合,及相似注解的差异这三方面着手。
1.按功能分类
本文仅讨论Spring Boot Test(版本:2.1.1.BUILD-SNAPSHOT)中的注解,原Spring Test中的注解将在其他文章中讨论。
由于使用这些注解的使用方式大多比较简单,为避免干扰阅读,本文不再罗列代码示例。若有想观看示例的开发者,可以查看GitHub官方Sample或spring-boot-test和spring-boot-test-autoconfigure的单元测试
从功能上讲,Spring Boot Test中的注解主要分如下几类:
类别 | 示例 | 格式 | 说明 |
---|---|---|---|
配置类型 | @TestConfiguration 等 |
提供一些测试相关的配置入口 | |
mock类型 | @MockBean 等 |
提供mock支持 | |
启动测试类型 | @SpringBootTest |
@\*Test |
以Test结尾的注解,具有加载applicationContext的能力 |
自动配置类型 | @AutoConfigureJdbc 等 |
@AutoConfigure* |
以AutoConfigure开头的注解,具有加载测试支持功能的能力。 |
1.1 配置类型的注解
注解 | 作用 | 实践中的使用 |
---|---|---|
@TestComponent |
该注解另一种@Component ,在语义上用来指定某个Bean是专门用于测试的。 |
该注解适用于测试代码和正式混合在一起时,不加载被该注解描述的Bean,使用不多。 |
@TestConfiguration |
该注解是另一种@TestComponent ,它用于补充额外的Bean或覆盖已存在的Bean |
在不修改正式代码的前提下,使配置更加灵活 |
@TypeExcludeFilters |
用来排除@TestConfiguration 和@TestComponent |
适用于测试代码和正式代码混合的场景,使用不多 |
@OverrideAutoConfiguration |
可用于覆盖@EnableAutoConfiguration ,与ImportAutoConfiguration 结合使用,以限制所加载的自动配置类 |
在不修改正式代码的前提下,提供了修改配置自动配置类的能力 |
@PropertyMapping |
定义@AutoConfigure* 注解中用到的变量名称,例如在@AutoConfigureMockMvc 中定义名为spring.test.mockmvc.webclient.enabled的变量 |
一般不使用 |
使用
@SpringBootApplication
启动测试或者生产代码,被@TestComponent
描述的Bean会自动被排除掉。如果不是则需要向@SpringBootApplication
添加TypeExcludeFilter。
1.2 mock类型的注解
注解 | 作用 |
---|---|
@MockBean |
用于mock指定的class或被注解的属性 |
@MockBeans |
使@MockBean 支持在同一类型或属性上多次出现 |
@SpyBean |
用于spy指定的class或被注解的属性 |
@SpyBeans |
使@SpyBeans 支持在同一类型或属性上多次出现 |
@MockBean
和@SpyBean
这两个注解,在mockito框架中本来已经存在,且功能基本相同。Spring Boot Test又定义一份重复的注解,目的在于使MockBean
和SpyBean
被ApplicationContext管理,从而方便使用。
MockBean和SpyBean功能非常相似,都能模拟方法的各种行为。不同之处在于MockBean是全新的对象,跟正式对象没有关系;而SpyBean与正式对象紧密联系,可以模拟正式对象的部分方法,没有被模拟的方法仍然可以运行正式代码。
1.3 自动配置类型的注解(@AutoConfigure*)
注解 | 作用 |
---|---|
@AutoConfigureJdbc |
自动配置JDBC |
@AutoConfigureCache |
自动配置缓存 |
@AutoConfigureDataLdap |
自动配置LDAP |
@AutoConfigureJson |
自动配置JSON |
@AutoConfigureJsonTesters |
自动配置JsonTester |
@AutoConfigureDataJpa |
自动配置JPA |
@AutoConfigureTestEntityManager |
自动配置TestEntityManager |
@AutoConfigureRestDocs |
自动配置Rest Docs |
@AutoConfigureMockRestServiceServer |
自动配置 MockRestServiceServer |
@AutoConfigureWebClient |
自动配置 WebClient |
@AutoConfigureWebFlux |
自动配置 WebFlux |
@AutoConfigureWebTestClient |
自动配置 WebTestClient |
@AutoConfigureMockMvc |
自动配置 MockMvc |
@AutoConfigureWebMvc |
自动配置WebMvc |
@AutoConfigureDataNeo4j |
自动配置 Neo4j |
@AutoConfigureDataRedis |
自动配置 Redis |
@AutoConfigureJooq |
自动配置 Jooq |
@AutoConfigureTestDatabase |
自动配置Test Database,可以使用内存数据库 |
这些注解可以搭配@\*Test
使用,用于开启在@\*Test
中未自动配置的功能。例如@SpringBootTest
和@AutoConfigureMockMvc
组合后,就可以注入org.springframework.test.web.servlet.MockMvc
。
“自动配置类型”有两种使用方式:
- 在功能测试(即使用
@SpringBootTest
)时显示添加。- 一般在切片测试中被隐式使用,例如
@WebMvcTest
注解时,隐式添加了@AutoConfigureCache
、@AutoConfigureWebMvc
、@AutoConfigureMockMvc
。
实现原理
与spring-boot-autoconfigure
中的@\*AutoConfiguration
实现略有不同,Test包中的@AutoConfigure\*
通过DeterminableImports
接口作为指定代码的识别入口,通过ImportAutoConfiguration
注解作为配置入口,从Test包下的spring.factories
读取配置文件,每个@AutoConfigure\*
中都可以包含多个Spring Boot的@\*AutoConfiguration
,例如:
1.4 启动测试类型的注解(@*Test)
所有的@*Test注解都被@BootstrapWith
注解,它们可以启动ApplicationContext,是测试的入口,所有的测试类必须声明一个@*Test注解。
注解 | 作用 | |
---|---|---|
@SpringBootTest |
自动侦测并加载@SpringBootApplication或@SpringBootConfiguration中的配置,默认web环境为MOCK,不监听任务端口 | |
@DataRedisTest |
测试对Redis操作,自动扫描被@RedisHash描述的类,并配置Spring Data Redis的库 | |
@DataJpaTest |
测试基于JPA的数据库操作,同时提供了TestEntityManager替代JPA的EntityManager | |
@DataJdbcTest |
测试基于Spring Data JDBC的数据库操作 | |
@JsonTest |
测试JSON的序列化和反序列化 | |
@WebMvcTest |
测试Spring MVC中的controllers | |
@WebFluxTest |
测试Spring WebFlux中的controllers | |
@RestClientTest |
测试对REST客户端的操作 | |
@DataLdapTest |
测试对LDAP的操作 | |
@DataMongoTest |
测试对MongoDB的操作 | |
@DataNeo4jTest |
测试对Neo4j的操作 |
除了
@SpringBootTest
之外的注解都是用来进行切面测试的,他们会默认导入一些自动配置,点击官方docs查看详情。
一般情况下,推荐使用@SpringBootTest
而非其它切片测试的注解,简单有效。若某次改动仅涉及特定切片,可以考虑使用切片测试。
@SpringBootTest
是这些注解中最常用的一个,其中包含的配置项如下:
配置名称 | 说明 |
---|---|
value |
指定配置属性 |
properties |
指定配置属性,和value意义相同 |
classes |
指定配置类,等同于@ContextConfiguration 中的class,若没有显示指定,将查找嵌套的@Configuration 类,然后返回到SpringBootConfiguration 搜索配置 |
webEnvironment |
指定web环境,可选值有:MOCK 、RANDOM_PORT 、DEFINED_PORT 、NONE |
webEnvironment
详细说明:
可选值 | 说明 |
---|---|
MOCK |
此值为默认值,该类型提供一个mock环境,此时内嵌的服务(servlet容器)并没有真正启动,也不会监听web端口。 |
RANDOM_PORT |
启动一个真实的web服务,监听一个随机端口。 |
DEFINED_PORT |
启动一个真实的web服务,监听一个定义好的端口(从配置中读取)。 |
NONE |
启动一个非web的ApplicationContext,既不提供mock环境,也不提供真是的web服务。 |
2. 相互之间的搭配组合
典型的搭配如下
package sample.test;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import sample.test.domain.VehicleIdentificationNumber;
import sample.test.service.VehicleDetails;
import sample.test.service.VehicleDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.test.context.junit4.SpringRunner;
import static org.mockito.BDDMockito.given;
/**
* {@code @SpringBootTest} with a random port for {@link SampleTestApplication}.
*
* @author Phillip Webb
*/
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureTestDatabase
public class SampleTestApplicationWebIntegrationTests {
private static final VehicleIdentificationNumber VIN = new VehicleIdentificationNumber(
"01234567890123456");
@Autowired
private TestRestTemplate restTemplate;
@MockBean
private VehicleDetailsService vehicleDetailsService;
@Before
public void setup() {
given(this.vehicleDetailsService.getVehicleDetails(VIN))
.willReturn(new VehicleDetails("Honda", "Civic"));
}
@Test
public void test() {
this.restTemplate.getForEntity("/{username}/vehicle", String.class, "sframework");
}
}
- @RunWith(SpringRunner.class)是JUnit的注解,作用是关联Spring Boot Test,使运行JUnit时同时启动Spring
- @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) 作用是启动Spring的ApplicationContext,参数webEnvironment指定了运行的web环境
- @AutoConfigureTestDatabase 作用是启动一个内存数据库,不使用真实的数据库
其中@RunWith和@*Test必须存在,@AutoConfigure*可以同时配置任意多个,而配置类型的注解可以在需要时添加。
3. 相似注解的区别和联系
3.1 @TestComment vs @Comment
@TestComponent
是另一种@Component
,在语义上用来指定某个Bean是专门用于测试的- 使用@SpringBootApplication服务时,
@TestComponent
会被自动排除
3.2 @TestConfiguration vs @Configuration
@TestConfiguration
是Spring Boot Boot Test提供的,@Configuration
是Spring Framework提供的。@TestConfiguration
实际上是也是一种@TestComponent
,只是这个@TestComponent
专门用来做配置用。@TestConfiguration
和@Configuration
不同,它不会阻止@SpringBootTest
的查找机制,相当于是对既有配置的补充或覆盖。
3.3 @SpringBootTest vs @WebMvcTest(或@*Test)
- 都可以启动Spring的ApplicationContext
@SpringBootTest
自动侦测并加载@SpringBootApplication
或@SpringBootConfiguration
中的配置,@WebMvcTest
不侦测配置,只是默认加载一些自动配置。@SpringBootTest
测试范围一般比@WebMvcTest
大。
3.4 @MockBean vs @SpyBean
4. 小结
本文主要介绍了Spring Boot Test中新增的注解,笔者将这些注解分为这几个类型:配置类型、mock类型、启动测试类型、自动配置类型。
- “配置类型”中的
@TestComponent
、@TestConfiguration
、@OverrideAutoConfiguration
使配置更加灵活。 - 封装了
mockito
的@MockBean
和@SpyBean
,使其可以自然的注入到Spring容器中。 - 每个测试类必须包含一个“启动测试类型”的注解(
@\*Test
),同时可以根据需要添加”自动配置类型”的注解(@AutoConfigure*
)。 @SpringBootTest
是最常用的“启动测试类型”注解
参考:
Spring Boot Reference Guide
Spring、Spring Boot和TestNG测试指南 - @TestConfiguration - 颇忒脱 - SegmentFault 思否
OverrideAutoConfiguration (Spring Boot Docs 2.1.0.RELEASE API)
Spring Boot 1.4: @MockBean and @SpyBean | GoorooThink Tech News | Articles | Skills Analytics | Gooroo