摘要:软件测试是软件开发中必不可少的一个环节。对于开发者来说,编写测试用例也是开发中的一项重要工作。测试用例可以检测代码编写的质量,帮助开发人员及时发现和处理程序的漏洞,同时更深入地了解业务需求。本章主要讲解Spring Boot Test的使用示例,以及如何通过S
软件测试是软件开发中必不可少的一个环节。对于开发者来说,编写测试用例也是开发中的一项重要工作。测试用例可以检测代码编写的质量,帮助开发人员及时发现和处理程序的漏洞,同时更深入地了解业务需求。本章主要讲解Spring Boot Test的使用示例,以及如何通过Spring Boot简化应用程序的打包方式,并部署应用程序。
Spring Boot提供了许多公用方法与注解,可以帮助开发者测试应用程序。Spring Boot主要包括spring-boot-test与spring-boottest-autoconfigure核心模块。Spring Boot提供了spring-bootstarter-test的Starter,主要集成了junit Jupiter、AssertJ和Hamcrest等常用测试框架。
Spring Boot测试简介
在Spring Boot Test诞生之前,常用的测试框架是JUnit等。
Spring Boot Test诞生后,集成了上述测试框架。Spring框架的一个主要优势是更容易集成单元测试,可以通过new操作符直接生成实例,或者用mock对象代替真实的依赖。通常,测试不只是单元测试,还有集成测试,Spring Boot Test可以在不部署应用程序的前提下进行集成测试。
使用Spring Boot Test,需要在项目中增加spring-bootstarter-test的Starter依赖,具体如下:
org.springframework.boot
spring-boot-starter-test
test
使用@SpringBootTest注解,即可进行测试。
如果项目中依赖spring-boot-starter-test,则自动添加以下类库。
JUnit 5:标准的测试框架。
Spring Test与Spring Boot Test:集成测试与公共类。
AssertJ:断言库。
Hamcrest:matcher库。
Mockito:mock库。
JSONassert:为JSON提供断言功能。
JsonPath:为JSON提供XPath功能。
通常情况下,Spring Boot Test支持的测试种类可以分为以下3种:
单元测试:主要用于测试类功能等。
切片测试:介于单元测试与集成测试之间,在特定环境下才能执行。
集成测试:测试一个完整的功能逻辑。
为了避免复杂的配置,Spring引入了大量的注解方式进行测试,这样可以减轻很多工作量。让读者理解并学会使用这些注解是本节学习的主要目标,了解这些注解,可以帮助读者更加容易地掌握SpringBoot Test的整个框架。
1. @SpringBootTest注解
Spring Boot用@SpringBootTest注解替代了spring-test中的@ContextConfiguration注解,该注解可以创建ApplicationContext,而且还添加了一些其他注解来测试特定的应用。使用@SpringBootTest的WebEnvironment属性来修改测试的运行方式。
MOCK:加载Web应用程序上下文并提供模拟的Web环境。该注解不会启动嵌入的服务器,可以结合@AutoConfigureMockMvc和@AutoConfigureWebTest-Client注解使用。
RANDOM_PORT:加载WebServerApplicationContext并提供真实的Web环境,嵌入的服务器启动后可以监听随机端口。
DEFINED_PORT:加载WebServerApplicationContext并提供真实的Web环境,嵌入的服务器启动后可以监听特定的端口。特定的端口可以从application.properties获取,也可以设置为默认的8080端口。
NONE:使用SpringApplication加载ApplicationContext,但不提供任何Web环境。
示例代码如下:
import org.junit.jupiter.api.Test;
import
org.springframework.Beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import
org.springframework.boot.test.context.SpringBootTest.Web
Environment;
import
org.springframework.boot.test.web.client.TestRestTemplate;
import static org.assertj.core.api.Assertions.assertThat;
//定义测试类
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class RandomPortTestRestTemplateExampleTests {
@Test
void exampleTest(@Autowired TestRestTemplate
restTemplate) {
String body = restTemplate.getForObject("/",
String.class);
assertThat(body).isEqualTo("Hello World"); //返回
结果断言
}
}
2. @RunWith注解
Spring Boot Test默认使用JUnit 5框架,
@RunWith(SpringRunner.class)注解可方便开发者使用JUnit 4框架。
使用方式如下:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment =
SpringBootTest.WebEnvironment.
RANDOM_PORT)
class DemoApplicationTests { ... }
3. @WebMvcTest注解
如果要测试Spring MVC controllers是否按预期那样工作,则用@WebMvcTest注解。@WebMvcTest注解可自动配置Spring MVC,并会限制扫描@Controller和@ControllerAdvice等注解的Bean。
通常,@WebMvcTest仅限于单个Controller,并结合@MockBean注解提供对某个类的模拟实现。@WebMvcTest还会自动配置MockMvc。
MockMvc提供了一个强大的方法可以快速测试MVC控制器,并且无须启动一个完整的HTTP服务器。示例代码如下:
import org.junit.jupiter.api.*;
import org.springframework.beans.factory.annotation.*;
import
org.springframework.boot.test.autoconfigure.web.servlet.*;
import org.springframework.boot.test.mock.mockito.*;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.BDDMockito.*;
import static
org.springframework.test.web.servlet.request.MockMvc
RequestBuilders.*;
import static
org.springframework.test.web.servlet.result.MockMvc
ResultMatchers.*;
@WebMvcTest(UserVehicleController.class)
class MyControllerTests {
@Autowired
private MockMvc mvc; //注入
MockMvc
@MockBean
private UserVehicleService userVehicleService;
@Test
void testExample throws Exception {
given(this.userVehicleService.getVehicleDetails("sboot"))
.willReturn(new VehicleDetails("Honda",
"Civic"));
this.mvc.perform(get("/sboot/vehicle").accept(MediaType.
TEXT_PLAIN))
.andExpect(status.isOk).andExpect(content.
string("Honda Civic"));
}
}
4. @WebFluxTest注解
@DataJPATest注解可以测试JPA应用。默认情况下,该注解会扫描@Entity注解的类及repositories类。@DataJpaTest注解不会扫描@Component和@Configuration-Properties注解的对象。示例代码如下:
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.autoconfigure.orm.jpa.*;
import static org.assertj.core.api.Assertions.*;
//JPA测试
@DataJpaTest
class ExampleRepositoryTests {
@Autowired
private TestEntityManager entityManager;
@Autowired
private UserRepository repository;
@Test
void testExample throws Exception {
this.entityManager.persist(new User("sboot",
"1234"));
User user = this.repository.findByUsername("sboot");
assertThat(user.getUsername).isEqualTo("sboot");
//断言用户名
assertThat(user.getVin).isEqualTo("1234");
}
}
5. @DataMongoTest注解
@DataMongoTest注解可以用来测试MongoDB程序。默认会配置一个嵌入的MongoDB并配置一个MongoTemplate对象,然后扫描@Document注解类。示例代码如下:
import
org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.boot.test.autoconfigure.data.mongo.Data
MongoTest;
import org.springframework.data.mongodb.core.MongoTemplate;
//Mongo测试
@DataMongoTest
class ExampleDataMongoTests {
@Autowired
private MongoTemplate mongoTemplate;
...
}
6. @DataRedisTest注解
@DataRedisTest注解用来测试Redis应用程序。示例代码如下:
import
org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.boot.test.autoconfigure.data.redis.Data
RedisTest;
//Redis测试
@DataRedisTest
class ExampleDataRedisTests {
@Autowired
private YourRepository repository;
...
}
7. @RestClientTest注解
@RestClientTest注解用来测试REST clients。默认情况下会自动配置Jackson、GSON、Jsonb、RestTemplateBuilder,以及对MockRestServiceServer的支持。示例代码如下:
@RestClientTest(RemoteVehicleDetailsService.class)
class ExampleRestClientTest {
@Autowired
private RemoteVehicleDetailsService service;
@Autowired
private MockRestServiceServer server;
@Test
void
getVehicleDetailsWhenResultIsSuccessShouldReturnDetails
throws Exception {
this.server.expect(requestTo("/greet/details"))
.andRespond(withSuccess("hello",
MediaType.TEXT_PLAIN));
String greeting = this.service.callRestService;
assertThat(greeting).isEqualTo("hello");
}
}
8. @AutoConfigureMockMvc注解
@SpringBootTest注解通常不会启动服务器,如果在测试中用Web端点进行测试,可以添加MockMvc配置。示例代码如下:
import org.junit.jupiter.api.Test;
import
org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.boot.test.autoconfigure.web.servlet.
AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import static
org.springframework.test.web.servlet.request.MockMvc
RequestBuilders.get;
import static
org.springframework.test.web.servlet.result.MockMvc
ResultMatchers.content;
import static
ResultMatchers.status;
@SpringBootTest
@AutoConfigureMockMvc
class MockMvcExampleTests {
@Test
void exampleTest(@Autowired MockMvc mvc) throws Exception
{
mvc.perform(get("/")).andExpect(status.isOk).andExpect
(content.string("Hello World"));
}
}
9. @MockBean注解
测试的过程中某些场景需要模拟一些组件,这时就需要使用
@MockBean注解。示例代码如下:
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.*;
import org.springframework.boot.test.context.*;
import org.springframework.boot.test.mock.mockito.*;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.BDDMockito.*;
@SpringBootTest
class MyTests {
@MockBean
private RemoteService remoteService;
@Autowired
private Reverser reverser;
@Test
void exampleTest {
given(this.remoteService.someCall).willReturn("mock");
String reverse = reverser.reverseSomeCall;
assertThat(reverse).isEqualTo("kcom");
}
}
Spring Boot的灵活打包方式在部署应用程序时也提供了大量的部署方式。开发中可以将Spring Boot应用程序部署到各种云平台或虚拟机上。本节主要介绍一些常见的部署场景。
JAR包部署
Spring Boot通常采用JAR包进行部署并提供Maven打包插件,代码如下:
spring-boot-Maven-plugin
true
执行Maven命令:
mvn clean package
打好JAR包后,执行以下命令即可完成JAR包的部署。
.jarDocker部署
Docker是一个虚拟环境容器,可以将开发环境、代码及配置文件等一并打包到这个容器中,并发布并应用到任意平台上。如果要在Docker环境中运行Spring Boot应用程序,需要一个Docker镜像文件。
构建Docker镜像文件需要Dockerfile文件,例如:
FROM openjdk:8-jdk-alpine
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
打包镜像命令如下:
docker build -t springio/gs-spring-boot-docker .
运行镜像命令如下:
docker run -p 8080:8080 springio/gs-spring-boot-docker
来源:大数据架构师