感谢作者:https://www.jianshu.com/p/d8f844711bf4
本章目的
基于SpringBoot
平台整合Junit
分别完成客户端
、服务端
的单元测试
。
构建项目
添加相关依赖Web、MySQL、JPA、Druid、Lombok
<dependencies>
<!--data jpa依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!--web依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.9</version>
</dependency>
<!--lombok依赖-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--MySQL依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- tomcat -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<!--<scope>provided</scope>-->
</dependency>
<!--springboot程序测试依赖,创建项目默认添加-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
准备并配置数据库
good_infos
application.yml
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8
username: root
password: root
druid:
#最大活跃数
maxActive: 20
#初始化数量
initialSize: 1
#最大连接等待超时时间
maxWait: 60000
#打开PSCache,并且指定每个连接PSCache的大小
poolPreparedStatements: false
maxPoolPreparedStatementPerConnectionSize: 20
#通过connectionProperties属性来打开mergeSql功能;慢SQL记录
#connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
minIdle: 1
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: select 1 from dual
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
#配置监控统计拦截的filters,去掉后监控界面sql将无法统计,'wall'用于防火墙
filters: stat, wall
jpa:
properties:
hibernate:
show_sql: true
format_sql: true
构建实体
/**
* @author Ray
* @date 2018/6/30 0030
* 商品基本信息实体
*/
@Data
@Entity
@Table(name = "good_infos")
public class GoodInfoEntity implements Serializable {
//商品编号
@Id
@Column(name = "tg_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer tgId;
//商品类型编号
@Column(name = "tg_type_id")
private Integer typeId;
//商品标题
@Column(name = "tg_title")
private String title;
//商品价格
@Column(name = "tg_price")
private double price;
//商品排序
@Column(name = "tg_order")
private int order;
}
构建测试控制器
/**
* @author Ray
* @date 2018/6/30 0030
*/
@RestController
public class TestController {
/**
* 商品基本信息数据接口
*/
@Autowired
private GoodInfoJPA goodInfoJPA;
/**
* 查询首页内容
*/
@RequestMapping(value = "/index")
public String index(String name){
return "this is index page" + name;
}
/**
* 查询全部商品
*/
@RequestMapping(value = "/all")
public List<GoodInfoEntity> selectAll(){
return goodInfoJPA.findAll();
}
/**
* 查询商品详情
*/
@RequestMapping(value = "/detail", method = RequestMethod.GET)
public Optional<GoodInfoEntity> selectOne(Integer tgId){
return goodInfoJPA.findById(tgId);
}
}
编写单元测试
/**
* 单元测试
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class Lesson35ApplicationTests {
/**
* 模拟mvc测试对象
* 这个类是Spring为我们提供模拟SpringMVC请求的实例类
*/
private MockMvc mockMvc;
/**
* web 项目上下文
*/
@Autowired
private WebApplicationContext webApplicationContext;
/**
* 商品业务数据接口
*/
@Autowired
private GoodInfoJPA goodInfoJPA;
/**
* 所有测试方法执行之前执行该方法
*/
@Before
public void before(){
// 获取mockmvc对象实例
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
/**
* 测试访问/index地址(已测试)
*/
@Test
public void testIndex() throws Exception {
MvcResult mvcResult = mockMvc
.perform( //perform方法其实只是为了构建一个请求,并且返回ResultActions实例,该实例则是可以获取到请求的返回内容。
MockMvcRequestBuilders.get("/index")
//param方法用于在发送请求时携带参数,当然除了该方法还有很多其他的方法,大家可以根据实际请求情况选择调用。
.param("name", "admin")
)
//andReturn方法则是在发送请求后需要获取放回时调用,该方法返回MvcResult对象,该对象可以获取到返回的视图名称、返回的Response状态、获取拦截请求的拦截器集合等。
.andReturn();
//MvcResult对象实例获取的MockHttpServletResponse对象从而才得到的Status状态码。
int status = mvcResult.getResponse().getStatus();
//同样也是使用MvcResult实例获取的MockHttpServletResponse对象从而得到的请求返回的字符串内容。
String responseString = mvcResult.getResponse().getContentAsString();
//使用Junit内部验证类Assert判断返回的状态码是否正常为200
Assert.assertEquals("请求错误", 200, status);
//判断返回的字符串是否与我们预计的一样。
Assert.assertEquals("返回结果不一致", "this is index pageadmin", responseString);
}
@Test
public void testAll() throws Exception {
MvcResult mvcResult = mockMvc
.perform(
MockMvcRequestBuilders.get("/all")
)
.andReturn();
int status = mvcResult.getResponse().getStatus();
String responseString = mvcResult.getResponse().getContentAsString();
Assert.assertEquals("return status not equals 200", 200, status);
System.out.println(responseString);
}
/**
* 测试查询详情(已测试)
*/
@Test
public void testDetail() throws Exception {
MvcResult mvcResult = mockMvc
.perform(
//需要请求的本项目的相对路径
MockMvcRequestBuilders.get("/detail")
//param方法用于在发送请求时携带参数
.param("tgId", "1")
)
//发送请求后需要获取放回时调用
.andReturn();
// 输出拦截器
HandlerInterceptor[] interceptors = mvcResult.getInterceptors();
System.out.println("拦截器: " + interceptors[0].getClass().getName());
int status = mvcResult.getResponse().getStatus();
String responseString = mvcResult.getResponse().getContentAsString();
System.out.println("返回内容: " + responseString);
Assert.assertEquals("return status not equals 200", 200, status);
}
/**
* 测试添加商品基本信息(已测试)
*/
@Test
public void testInsert(){
/**
* 商品基本信息实体
*/
GoodInfoEntity goodInfoEntity = new GoodInfoEntity();
goodInfoEntity.setTitle("西红柿3");
goodInfoEntity.setOrder(23);
goodInfoEntity.setPrice(5.83);
goodInfoEntity.setTypeId(3);
goodInfoJPA.save(goodInfoEntity);
/**
* 测试是否添加成功
* 验证主键是否存在
*/
Assert.assertNotNull(goodInfoEntity.getTgId());
}
/**
* 测试删除商品基本信息(已测试)
*/
@Test
public void testDelete(){
// 根据主键删除
goodInfoJPA.deleteById(3);
// 验证数据库是否存在删除
Assert.assertNull(goodInfoJPA.findById(3));
}
@Test
public void contextLoads() {
}
}