在微服务架构下,整个系统被切割为 N 个独立的微服务相互配合来使用,那么对于系统可用性会有更高的要求。从大到小可以分为三个层级,开发人员编码需要做的单元测试、微服务和微服务之间的接口联调测试、微服务和微服务之间的集成测试,通过三层的严格测试才能有效保证系统的稳定性。
作为一名开发人员,严格做好代码的单元测试才是保证软件质量的第一步。Spring Boot 做为一个优秀的开源框架合集对测试的支持非常友好,Spring Boot 提供了专门支持测试的组件 Spring Boot Test,其集成了业内流行的 7 种强大的测试框架:
- JUnit,一个 Java 语言的单元测试框架;
- Spring Test,为 Spring Boot 应用提供集成测试和工具支持;
- AssertJ,支持流式断言的 Java 测试框架;
- Hamcrest,一个匹配器库;
- Mockito,一个 Java Mock 框架;
- JSONassert,一个针对 JSON 的断言库;
- JsonPath,JSON XPath 库。
这 7 种测试框架完整的支持了软件开发中各种场景,我们只需要在项目中集成 Spring Boot Test 即可拥有这 7 种测试框架的各种功能,并且 Spring 针对 Spring Boot 项目使用场景进行了封装和优化,以方便在 Spring Boot 项目中去使用,接下来介绍 Spring Boot Test 的使用。
快速入手
我们创建一个 spring-boot-test 项目来演示 Spring Boot Test 的使用,只需要在项目中添加 spring-boot-starter-test 依赖即可:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
测试方法
首先来演示一个最简单的测试,只是测试一个方法的执行:
public class HelloTest {
@Test
public void hello() {
System.out.println("hello world");
}
}
在 Idea 中点击 helle() 方法名,选择 Run hello() 即可运行,执行完毕控制台打印信息如下:
hello world
证明方法执行成功。
测试服务
大多数情况下都是需要测试项目中某一个服务的准确性,这个时候往往需要 Spring Boot 启动后的上下文环境,对于这种情况只需要添加两个注解即可支持。我们创建一个 HelloService 服务来演示。
public interface HelloService {
public void sayHello();
}
创建一个它的实现类:
@Service
public class HelloServieImpl implements HelloService {
@Override
public void sayHello() {
System.out.println("hello service");
}
}
在这个实现类中 sayHello() 方法输出了字符串:"hello service"。
为了可以在测试中获取到启动后的上下文环境(Beans),Spring Boot Test 提供了两个注解来支持,测试时只需在测试类的上面添加 @RunWith(SpringRunner.class) 和 @SpringBootTest 注解即可。
@RunWith(SpringRunner.class)
@SpringBootTest
public class HelloServiceTest {
@Resource
HelloService helloService;
@Test
public void sayHelloTest(){
helloService.sayHello();
}
}
同时在测试类中注入 HelloService,sayHelloTest 测试方法中调用 HelloService 的 sayHello() 方法,执行测试方法后,就会发现在控制台打印出了 Spring Boot 的启动信息,说明在执行测试方法之前,Spring Boot 对容器进行了初始化,输出完启动信息后会打印出以下信息:
hello service
证明测试服务成功,但是这种测试会稍显麻烦,因为控制台打印了太多的东西,需要我们来仔细分辨,这里有更优雅的解决方案,可以利用 OutputCapture 来判断 System 是否输出了我们想要的内容,添加 OutputCapture 改造如下。
import static org.assertj.core.api.Assertions.assertThat;
import org.springframework.boot.test.rule.OutputCapture;
@RunWith(SpringRunner.class)
@SpringBootTest
public class HelloServiceTest {
@Rule
public OutputCapture outputCapture = new OutputCapture();
@Resource
HelloService helloService;
@Test
public void sayHelloTest(){
helloService.sayHello();
assertThat(this.outputCapture.toString().contains("hello service")).isTrue();