目录

  • 1 初识Java EE
    • 1.1 新建目录
    • 1.2 新建目录
  • 2 Spring Boot知识回顾
    • 2.1 学习目标
    • 2.2 ​Spring Boot简介
      • 2.2.1 Eclipse中Spring Boot开发环境安装
      • 2.2.2 Eclipse中手工构建Spring Boot项目(一)
      • 2.2.3 Eclipse中手工构建Spring Boot项目(二)
      • 2.2.4 Spring Tool Suite中构建Spring boot项目
      • 2.2.5 Spring Boot的开发步骤
  • 3 Spring Boot核心配置
    • 3.1 学习目标
    • 3.2 Spring Boot核心配置
    • 3.3 基本配置
    • 3.4 日志配置
    • 3.5 读取应用配置
  • 4 Spring Boot的Web开发
    • 4.1 学习目标
    • 4.2 Spring Boot的Web开发支持
    • 4.3 Thymeleaf模板引擎
      • 4.3.1 Spring Boot与Thymeleaf实现页面信息国际化
      • 4.3.2 Spring Boot与Thymeleaf的表单验证
    • 4.4 Spring Boot处理JSON数据
    • 4.5 Spring Boot文件上传与下载
    • 4.6 Spring Boot的异常统一处理
    • 4.7 Spring Boot对JSP的支持
    • 4.8 Spring Boot与MyBatis的集成
    • 4.9 Spring Boot与MyBatis整合(项目重构)
  • 5 Spring Boot的数据访问
    • 5.1 学习目标
    • 5.2 REST
      • 5.2.1 REST 简介
      • 5.2.2 Spring Boot整合REST
      • 5.2.3 Spring Data REST
    • 5.3 Spring Data JPA
      • 5.3.1 简单条件查询-案例专家抽取系统
      • 5.3.2 关联查询 (一对一)
      • 5.3.3 关联查询 (一对多)
      • 5.3.4 关联查询 (多对多)
      • 5.3.5 @Query和@Modifying注解
      • 5.3.6 排序与分页查询
    • 5.4 Spring Boot使用JdbcTemplate
    • 5.5 Spring Boot的事务管理
    • 5.6 MongoDB
    • 5.7 Redis
      • 5.7.1 安装Redis
      • 5.7.2 SpringBoot整合Redis
      • 5.7.3 使用StringRedisTemplate和RedisTemplate
    • 5.8 数据缓存Cache
      • 5.8.1 Spring Boot缓存支持
      • 5.8.2 Redis Cache运行测试
      • 5.8.3 ehCache
  • 6 Spring Boot的安全控制
    • 6.1 学习目标
    • 6.2 Spring Security快速入门
    • 6.3 基于Spring Data JPA的Spring Boot Security操作实例
    • 6.4 基于MyBatis的Spring Boot Security操作实例
  • 7 异步消息
    • 7.1 学习目标
    • 7.2 消息模型
    • 7.3 JMS消息代理
    • 7.4 AMQP消息代理
  • 8 Spring Boot的热部署与单元测试
    • 8.1 学习目标
    • 8.2 开发的热部署
      • 8.2.1 模板引擎的热部署
      • 8.2.2 使用spring-boot-devtools进行热部署
    • 8.3 Spring Boot的单元测试
  • 9 监控Spring Boot应用
    • 9.1 学习目标
    • 9.2 端点的分类与测试
    • 9.3 自定义端点
    • 9.4 自定义HealthIndicator
  • 10 电子商务平台开发
    • 10.1 学习目标
    • 10.2 系统设计与实现
    • 10.3 后台管理子系统
    • 10.4 前端页面子系统
Spring Boot的单元测试

Spring Boot的单元测试

Spring Boot为测试提供了一个名为spring-boot-starter-test的Starter。我们使用STS创建Spring Boot应用时,将自动添加spring-boot-starter-test依赖。这样在测试时,就没有必要再添加额外的JAR包。spring-boot-starter-test主要提供了以下测试库:

1.Junit:标准的单元测试Java应用程序。

2.Spring Test&Spring Boot Test:针对Spring Boot应用程序的单元测试。

3.Mockito:Java mocking框架,用于模拟任何Spring管理的Bean,比如在单元测试中模拟一个第三方系统Service接口返回的数据,而不去真正调用第三方系统。

4.AssertJ:一个流畅的assertion库,同时也提供了更多的期望值与测试返回值的比较方式。

5.JSONassert:对JSON对象或JSON字符串断言的库。

6.JsonPath:提供类似Xpath(一门在XML文档中查找信息的语言)那样的符号来获取JSON数据片段。

一、 Spring Boot单元测试程序模板

@RunWith(SpringRunner.class)

@SpringBootTest

public class GoodsServiceTest {

//注入要测试的service

@Autowired

private GoodsService goodsService;

@Test

public void testGoodsService() {

//调用GoodsService的方法进行测试

}

}

@RunWith注解是JUnit标准的一个注解,目的是用来告诉JUnit框架不要使用内置的方式进行单元测试,而应使用@RunWith指明的类来进行单元测试,所有的Spring单元测试总是使用SpringRunner.class。

@SpringBootTest用于Spring Boot应用测试,它默认根据包名逐级往上找,一直找到Spring Boot主程序(包含@SpringBootApplication注解的类),并在单元测试时启动该主程序来创建Spring上下文环境。

二、 测试Service


    单元测试Service代码与通过Controller调用Service代码相比,需要特别考虑该Service是否依赖其他还未开发完毕的Service(第三方接口)。如果依赖其他还未开发完毕的Service,我们需要使用Mockito来模拟未完成的Service。

    假设,在UserService中依赖CreditService(第三方接口)的getCredit方法获得用户积分。

    那么,我们如何测试UserService呢?问题是单元测试不能实际调用CreditService(因为CreditService是第三方系统),因此,我们在单元测试类需要使用Mockito的注解@MockBean自动注入Spring管理的Service,用来提供模拟实现,在Spring上下文中,CreditService实现已经被模拟实现代替了。

三、测试Controller

    在Spring Boot应用中,可以单独测试Controller代码,用来验证与Controller相关的URL路径映射、文件上传、参数绑定、参数校验等特性。可以通过@WebMvcTest注解来完成Controller单元测试,当然也可以通过@SpringBootTest测试Controller。

    需要注意的是,我们在使用@WebMvcTest注解测试Controller时,带有@Service以及别的注解组件类不会自动被扫描注册为Spring容器管理的Bean,而@SpringBootTest注解告诉Spring Boot去寻找一个主配置类(一个带@SpringBootApplication的类),并使用它来启动Spring应用程序上下文,注入所有Bean。另外,还需要注意的是,MockMvc用来在Servlet容器内对Controller进行单元测试,并未真正发起了HTTP请求调用Controller。

    @WebMvcTest用于从服务器端对Controller层进行统一测试;如果需要从客户端与应用程序交互时,应该使用@SpringBootTest做集成测试。

四、模拟Controller请求

MockMvc的核心方法是:

public ResultActions perform(RequestBuilder requestBuilder)

RequestBuilder类可以通过调用MockMvcRequestBuilders的get、post、multipart等方法来模拟Controller请求,常用示例如下:

模拟一个get请求:

mvc.peform(get("/getCredit/{id}", uid));

模拟一个post请求:

mvc.peform(post("/getCredit/{id}", uid));

模拟文件上传:

mvc.peform(multipart("/upload").file("file", "文件内容".getBytes("UTF-8")));

模拟请求参数:

//模拟提交errorMessage参数

mvc.peform(get("/getCredit/{id}/{uname}", uid, uname).param("errorMessage", "用户名或密码错误"));

//模拟提交check

mvc.peform(get("/getCredit/{id}/{uname}", uid, uname).param("job", "收银员", "IT" ));

五、 比较Controller请求返回的结果

    我们知道,MockMvc的perform方法返回ResultActions实例,这个实例代表了请求Controller返回的结果。它提供了一系列andExpect方法来对请求Controller返回的结果进行比较。

mvc.peform(get("/getOneUser/10"))

.andExpect(status().isOk())  //期望请求成功,即状态码为200

//期望返回内容是application/json

.andExpect(content().contentType(MediaType.APPLICATION_JSON)) 

//使用JsonPath比较返回的JSON内容

.andExpect(jsonPath("$.name").value("chenheng")); //检查返回内容

1.比较返回的视图

mvc.peform(get("/getOneUser/10"))

.andExpect(view().name("/userDetail"));

2.比较模型

mvc.peform(post("/addOneUser"))

.andExpect(status().isOk())

.andExpect(model().size(1))

.andExpect(model().attributeExists("oneUser"))

.andExpect(model().attribute("oneUser", "chenheng"))

3.比较转发或重定向

mvc.peform(post("/addOneUser"))

.andExpect(forwardedUrl("/user/selectAll")); //或者 redirectedUrl("/user/selectAll")

4.比较返回的内容

andExpect(content().string("测试很好玩")); //比较返回的字符串

andExpect(content().xml(xmlContent)); //返回内容是XML,并且与xmlContent(变量)一样

andExpect(content().json(jsonContent)); //返回内容是JSON,并且与jsonContent(变量)一样

六、 测试实例

【例9-2】使用@WebMvcTest和@SpringBootTest两种方式测试某一个控制器方法。

1.创建基于Spring Data JPA的Web应用ch9_2

2.修改pom.xml文件,引入MySQL依赖

3.配置数据库连接等基本属性

4.创建持久化实体类

5.创建数据访问层

6.创建控制器层

7.创建测试用例(@WebMvcTest和@SpringBootTest)

8.运行