目标:适应公司系统软件组(Java)前后端分离开发的业务发展需求和更高质量代码要求。
前言:Spring-Boot项目只需要引入:spring-boot-starter-test 这个Starter 就可将SpringBoot 测试模块(包括JUnit,AssertJ, Mockito ,Hamcrest等有用的类库)引入项目。
开始前先了解比较常用的Annotations:
@RunWith(SpringRunner.class)
Enableannotations used in you Test-Class,即引入Spring Boot test支持(@before,@test,@After…).
@SpringBootTest
Addspring-boot features,初始化spring-boot工程上下文获得ApplicationContext.
@AutoConfigureMockMvc
ForMockMvc-based testing of your application 为了模拟发送/接收Restful请求.
@Transactional
Forrollback the transaction at the end of each test method by default,为了回滚测试数据.
@JsonTest
Totest that Object JSON serialization and deserialization is working as expected 测试JSON数据序列化和反序列化是否达预期效果
@BeforClass、@Before、@Test、@After、@AfterClass
Junit常用基本注解,不做介绍 ^-^
目前我们AMI产品化项目主利用spring-boot-starter-test对Controller层和Service层进行了单元测试。因为我们目前的开发是前后端分离,所以我们在Controller层利用Spring测试框架提供的MockMvc对象,模拟客户端-服务端的请求进行MVC测试,在服务端这边执行Controller的请求,这样就完全可以脱离依赖前端发起请求验证后端API。
下面分别对Controller层和Service层的单元测试做简要介绍:
ByThe way,单元测试命名方式:
类名:业务层名称+Tests eg:UserController 对应测试类名UserControllerTests
方法名:test+待测试方法名称 eg: 方法createUser()对应测试方法名为 testCreateUser()
一、Controller 层
在我们产品化项目中新建测试用例需分别在测试类顶部加入@RunWith(SpringRunner.class) 与 @SpringBootTest(Controller层与Service层测试类均要),其中Controller需多一个@AutoConfigureMockMvc用来引入MockMvc对象,MockMvc 用@Autowired 自动注入,具体如下图:
然后就是写具体方法的测试用例了,具体流程是:
1、 组装请求参数
2、 MockMvcRequestBuilder组装Post/Get/Put/Delete请求
3、 MockMvc调用perform()发起web请求
4、 Assert判断
具体列子如下:
组装请求:
1、 Controller中方法参数前存@equestBody的,需使用MockMvcRequestBuilders.content()传递参数,其他情况全部使用MockMvcRequestBuilders.param(“key”,”value”)传递(可多个),如下图
.accept(); 设置客户端可识别的内容类型
.contentType();设置请求头中的Content-Type字段,表示请求体的内容类型
2、 发起/建立请求
请求结果封装在MvcResult对象里面,其中andExpect(...)可以在perform(...)函数调用后多次调用,表示对多个条件的判断,这个函数的参数类型是ResultMatcher接口,在MockMvcResultMatchers这这个类中提供了很多返回ResultMatcher接口的工具函数。这个函数使得可以检测同一个web请求的多个方面,包括HTTP响应状态码(response status),响应的内容类型(content type),会话中存放的值,检验重定向、model或者header的内容等等
3、 Assert判断
assertThat等等;TestJson 待引入
二、Service层
比Controller层测试更简单,只需在测试类顶部加入@RunWith(SpringRunner.class) 与 @SpringBootTest注解,用@Autowired注入相应service 组件即可对相应接口方法进行单元测试,如下图
最后,为了节省时间提高效率我们需要打包测试功能,将多个单元测试class 一起执行测试,使用如下注解:
在我们AMI产品化项目中,我们统一用ApplicationSuiteTests.class打包全部单元测试用例,实现可以统一执行全部测试用例。运行结果如下:
Junit还提供了一个测试运行器--@RunWith(Parameteried.Class),其可以模拟不同的参数对方法进行测试,但是如果为每个类型参数创建一个方法,是很耗时,傻瓜式的,我们不考虑使用。
单元测试是验证代码第一道屏障,要养成每写一部分代码就进行单元测试的习惯,不要等到全部集成后再进行测试,集成后因为更关注整体运行效果,很容易遗漏掉代码底层的bug。