- Spring Boot提供很多有用的测试应用的工具。spring-boot-starter-test POM提供Spring Test,JUnit,Hamcrest和Mockito的依赖。在spring-boot核心模块org.springframework.boot.test包下也有很多有用的测试工具。
测试作用域依赖
如果使用spring-boot-starter-test ‘Starter POM’(在test作用域内),你将发现下列被提供的库:
1.Spring Test - 对Spring应用的集成测试支持
2.JUnit - 事实上的(de-facto)标准,用于Java应用的单元测试。
3.Hamcrest - 一个匹配对象的库(也称为约束或前置条件),它允许assertThat等JUnit类型的断言。
4.Mockito - 一个Java模拟框架。这也有一些我们写测试用例时经常用到的库。如果它们不能满足你的要求,你可以随意添加其他的测试用的依赖库。
测试Spring应用
依赖注入最大的优点就是它能够让你的代码更容易进行单元测试。你只需简单的通过new操作符实例化对象,而不需要涉及Spring。你也可以使用模拟对象替换真正的依赖。
你常常需要在进行单元测试后,开始集成测试(在这个过程中只需要涉及到Spring的ApplicationContext)。在执行集成测试时,不需要部署应用或连接到其他基础设施是非常有用的。
Spring框架包含一个dedicated测试模块,用于这样的集成测试。你可以直接声明对org.springframework:spring-test的依赖,或使用spring-boot-starter-test ‘Starter POM’以透明的方式拉取它。
如果你以前没有使用过spring-test模块,可以查看Spring框架参考文档中的相关章节。
测试Spring Boot应用
一个Spring Boot应用只是一个Spring ApplicationContext,所以在测试它时除了正常情况下处理一个vanilla Spring context外不需要做其他特别事情。唯一需要注意的是,如果你使用SpringApplication创建上下文,外部配置,日志和Spring Boot的其他特性只会在默认的上下文中起作用。
Spring Boot提供一个@SpringApplicationConfiguration注解用来替换标准的spring-test @ContextConfiguration注解。如果使用@SpringApplicationConfiguration来设置你的测试中使用的ApplicationContext,它最终将通过SpringApplication创建,并且你将获取到Spring Boot的其他特性。
示例如下:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SampleDataJpaApplication.class)
public class CityRepositoryIntegrationTests {
@Autowired
CityRepository repository;
// ...
}
提示:上下文加载器会通过查找@WebIntegrationTest或@WebAppConfiguration注解来猜测你想测试的是否是web应用(例如,是否使用MockMVC,MockMVC和@WebAppConfiguration是spring-test的一部分)。
如果想让一个web应用启动,并监听它的正常的端口,你可以使用HTTP来测试它(比如,使用RestTemplate),并使用@WebIntegrationTest注解你的测试类(或它的一个父类)。这很有用,因为它意味着你可以对你的应用进行全栈测试,但在一次HTTP交互后,你需要在你的测试类中注入相应的组件并使用它们断言应用的内部状态。
示例:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SampleDataJpaApplication.class)
@WebIntegrationTest
public class CityRepositoryIntegrationTests {
@Autowired
CityRepository repository;
RestTemplate restTemplate = new TestRestTemplate();
// ... interact with the running server
}
注:Spring测试框架在每次测试时会缓存应用上下文。因此,只要你的测试共享相同的配置,不管你实际运行多少测试,开启和停止服务器只会发生一次。
-
你可以为@WebIntegrationTest添加环境变量属性来改变应用服务器端口号,比如
@WebIntegrationTest("server.port:9000")。此外,你可以将server.port和management.port属性设置为0来让你的集成测试使用随机的端口号,例如:@RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = MyApplication.class) @WebIntegrationTest({"server.port=0", "management.port=0"}) public class SomeIntegrationTests { // ... } 可以查看Section 64.4, “Discover the HTTP port at runtime”,它描述了如何在测试期间发现分配的实际端口。
使用Spock测试Spring Boot应用
如果期望使用Spock测试一个Spring Boot应用,你应该将Spock的spock-spring模块依赖添加到应用的构建中。spock-spring将Spring的测试框架集成到了Spock里。
注意你不能使用上述提到的@SpringApplicationConfiguration注解,因为Spock找不到@ContextConfiguration元注解。为了绕过该限制,你应该直接使用@ContextConfiguration注解,并使用Spring Boot特定的上下文加载器来配置它。
@ContextConfiguration(loader = SpringApplicationContextLoader.class)
class ExampleSpec extends Specification {
// ...
}
注:上面描述的注解在Spock中可以使用,比如,你可以使用@WebIntegrationTest注解你的Specification以满足测试需要。
测试工具
- 打包进spring-boot的一些有用的测试工具类。
ConfigFileApplicationContextInitializer
- ConfigFileApplicationContextInitializer是一个ApplicationContextInitializer,可以用来测试加载Spring Boot的application.properties文件。当不需要使用@SpringApplicationConfiguration提供的全部特性时,你可以使用它。
@ContextConfiguration(classes = Config.class,initializers = ConfigFileApplicationContextInitializer.class)
EnvironmentTestUtils
- EnvironmentTestUtils允许你快速添加属性到一个ConfigurableEnvironment或ConfigurableApplicationContext。只需简单的使用key=value字符串调用它:java EnvironmentTestUtils.addEnvironment(env, "org=Spring", "name=Boot");
OutputCapture
- OutputCapture是一个JUnit Rule,用于捕获System.out和System.err输出。只需简单的将捕获声明为一个@Rule,并使用toString()断言:
import org.junit.Rule;
import org.junit.Test;
import org.springframework.boot.test.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
- TestRestTemplate是一个方便进行集成测试的Spring RestTemplate子类。你会获取到一个普通的模板或一个发送基本HTTP认证(使用用户名和密码)的模板。在任何情况下,这些模板都表现出对测试友好:不允许重定向(这样你可以对响应地址进行断言),忽略cookies(这样模板就是无状态的),对于服务端错误不会抛出异常。推荐使用Apache HTTP Client(4.3.2或更好的版本),但不强制这样做。如果在classpath下存在Apache HTTP Client,TestRestTemplate将以正确配置的client进行响应。
public class MyTest {
RestTemplate template = new TestRestTemplate();
@Test
public void testRequest() throws Exception {
HttpHeaders headers = template.getForEntity("http://myhost.com", String.class).getHeaders();
assertThat(headers.getLocation().toString(), containsString("myotherhost"));
}
}