自动化的单元测试,集成测试是项目持续集成的基础。在 Java 平台, JUnit, Mock 以及 Spring Boot Test 为编写自动化测试提供了强大的支持。
本文使用在 Spring Boot 构建Rest服务实验手册(一) 中使用的案例。如果不熟悉的 Spring Boot 的开发,可以先参考该实验手册。
增加依赖库
在 Spring Boot 中,JUnit, Mock 等相关的依赖已经加入到 Spring Boot Test 中,所以只需要在项目中加入如下依赖即可:
1 2 3 4 5
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
|
该依赖中默认加入的是 JUnit4
使用 JUnit 编写测试
因为 Spring 框架提倡 POJO 编程,所以一般业务层和展现层的代码都是 POJO, 所以可以直接用 JUnit 进行测试。
下面是测试案例中 TodoApi 的 ok() 方法的例子:
1 2 3 4 5 6 7 8
| public class JUnitTodoApiTester {
@Test public void testOk() { TodoApi todoApi = new TodoApi(); assertEquals(todoApi.ok(), "ok"); } }
|
对于需要调用业务层逻辑的方法,也可以采用 Mock 进行测试,如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| public class MockitoTodoApiTester {
@InjectMocks private TodoApi todoApi;
@Mock private TodoBiz todoBiz;
@Before public void init() { MockitoAnnotations.initMocks(this); }
@Test public void testGetTodoList() {
List<Todo> list = new ArrayList<>(); list.add(new Todo(1, "tom", "desc for tom")); when(todoBiz.listAll()).thenReturn(list);
ApiResult res = todoApi.getTodoList();
verify(todoBiz).listAll();
assertEquals(true, res.isSucc()); } }
|
使用 SpringBootTest 注解
在对 Sprng Boot 应用进行集成测试时,我们希望能启动整个 Spring Boot 的环境来进行测试,这时,可以采用 SpringBootTest 注解。 如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class TodoIntegrationTester {
@LocalServerPort private int port;
@Autowired private TestRestTemplate restTemplate;
@Test public void testOk() throws Exception {
String res = this.restTemplate.getForObject("http://localhost:" + port + "/todo/ok", String.class); assertEquals(res, "ok"); } }
|
在本例中,让应用在一个随机产生的端口启动,然后利用 TestRestTemplate 模拟用户进行访问,从而触发整体的流程来测试一个完整的功能。
如果不需要启动内嵌的服务器,也可以采用 Mock 的方法,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @RunWith(SpringRunner.class) @SpringBootTest @AutoConfigureMockMvc public class TodoIntegrationMockTester {
@Autowired private MockMvc mockMvc;
@Test public void testOk() throws Exception {
this.mockMvc.perform(get("/todo/ok")).andDo(print()).andExpect(status().isOk()).andExpect(content().string(containsString("ok"))); } }
|
同样可以测试一个功能的完整流程。