Spring Boot Test
Spring 框架提供了一个专门的测试模块(
spring-test
),用于应用程序的集成测试。 在 Spring Boot 中,你可以通过
spring-boot-starter-test
启动器快速开启和使用它。
# pom.xml
|
|
1. Junit 测试
当你的单元测试代码不需要用到 Spring Boot 功能,而只是一个简单的测试时,你可以直接编写你的 Junit 测试代码:
|
|
2. Spring Boot 测试
|
|
|
|
当运行 Spring Boot 应用程序测试时,它会自动的从当前测试类所在的包起一层一层向上搜索,直到找到一个
@SpringBootApplication
或
@SpringBootConfiguration
注释类为止。以此来确定如何装载 Spring 应用程序的上下文资源。只要你以合理的方式组织你的代码,你项目的主配置通常是可以被发现的。本示例项目的部分文件结构图为:
|
|
其中,主配置启动类的代码为:
|
|
如果搜索算法搜索不到你项目的主配置文件,将报出异常:
java.lang.IllegalStateException: Unable to find a @SpringBootConfiguration, you need to use @ContextConfiguration or @SpringBootTest(classes=…) with your test解决办法是,按 Spring Boot 的约定重新组织你的代码结构,或者手工指定你要装载的主配置文件:
|
|
基于 Spring 环境的 Junit 集成测试还需要使用
@RunWith(SpringJUnit4ClassRunner.class)
注解,该注解能够改变 Junit 并让其运行在 Spring 的测试环境,以得到 Spring 测试环境的上下文支持。否则,在 Junit 测试中,Bean 的自动装配等注解将不起作用。但由于 SpringJUnit4ClassRunner 不方便记忆,Spring 4.3 起提供了一个等同于 SpringJUnit4ClassRunner 的类 SpringRunner,因此可以简写成:
@RunWith(SpringRunner.class)
。
3. Spring MVC 测试
当你想对 Spring MVC 控制器编写单元测试代码时,可以使用
@WebMvcTest
注解。它提供了自配置的 MockMvc,可以不需要完整启动 HTTP 服务器就可以快速测试 MVC 控制器。
|
|
|
|
使用
@WebMvcTest
注解时,只有一部分的 Bean 能够被扫描得到,它们分别是:
@Controller
@ControllerAdvice
@JsonComponent
Filter
WebMvcConfigurer
HandlerMethodArgumentResolver
其他常规的
@Component
(包括
@Service
、
@Repository
等)Bean 则不会被加载到 Spring 测试环境上下文中。
如果测试的 MVC 控制器中需要
@Component
Bean 的参与,你可以使用
@MockBean
注解来协助完成:
|
|
|
|
4. Spring Boot Web 测试
|
|
|
|
5. Spring Data JPA 测试
当你想对 Spring Data JPA 应用进行单元测试时,你可以使用
@DataJpaTest
注解。并且在进行 JPA 测试时,你可以选择使用内存数据库还是真实的数据库测试。
5.1 内存数据库测试
默认情况下,
@DataJpaTest
使用的是内存数据库进行测试,你无需配置和启用真实的数据库。只需要在 pom.xml 配置文件中声明如下依赖即可:
# pom.xml
|
|
@DataJpaTest
注解它只扫描
@Entity
Bean 和装配 Spring Data JPA 存储库,其他常规的
@Component
(包括
@Service
、
@Repository
等)Bean 则不会被加载到 Spring 测试环境上下文。
|
|
|
|
|
|
5.2 真实数据库测试
如果你希望使用真实的数据库做测试,你可以使用
@AutoConfigureTestDatabase(replace = Replace.NONE)
注解:
|
|
replace = Replace.NONE
的作用是告知 Spring Boot 不要替换应用程序默认的数据源。
# src/main.resources/application.yml
|
|
5.3 事务控制
|
|
另外,你也可以使用
@Transactional
注解对事务进行控制。该注解可以标注在类级别做全局的控制,也可以标注在某个特定的方法级别上。如:
|
|