节操换外语 2018-04-05
【内容指引】
关闭微服务项目的缓存开关;
改造dto层代码;
改造dao层代码;
改造service.impl层的list方法;
调整单元测试类的testList方法代码。
在正式进行测试驱动开发之前,我们需要关闭项目的缓存配置。由于从“云开发”平台生成的微服务初始化代码默认启用了Redis缓存(建议以Docker的方式安装及启动Redis),为避免因为缓存导致测试数据不准确,可以关闭缓存的开关。
如下图所示,在"DocApplicationTests"中将“//TODO”提示这行删除掉即可:

在“DocApplication”中将“@EnableCaching”这个注解注释掉,就关掉了缓存开关:

在查询文档分类(Category)列表时,查询的参数通过“DTO数据传输对象”CategoryDTO传递。默认情况下,“云开发”平台初始化的DTO类代码中的字段来自于领域类中数据类型为String的字段,除此外,增加一个keyword字段。
keyword字段用于标准查询,其它字段用于高级查询。这里介绍下标准查询和高级查询的区别。
提示
由于本例中Category领域类仅包含name(分类名称)这一个String类型的字段,不便于区分标准查询和高级查询。我们假设Category类中还含有一个memo(分类说明)字段,那么标准查询和高级查询的用途如下:
标准查询
标准查询,就是“或”关系的匹配。客户端仅提供一个“查询关键字”,然后从Category领域类对应的数据表"tbl_category"的多个String字段中匹配该关键字(忽略大小写),只要任何一个字段匹配成功,即成为查询结果之一。比如,关键字为“AA”,那么如果分类名称(name)中含有“AA”,或者分类说明(memo)中含有“AA”,都是符合条件的。
高级查询
高级查询,就是“且”关系的匹配。客户端提供多个关键字,然后从Category领域类对应的数据表"tbl_category"的多个String字段中分别匹配这些关键字,只有所有字段的赋值均匹配成功,才能成为查询结果之一。比如,分类名称关键字为“AA”,分类说明关键字为“BB”,那么只有分类名称(name)中含有“AA”,并且分类说明(memo)中含有“BB”的数据才是符合条件的。

keyword字段是约定用于标准查询的参数,不可删除!
根据实际查询需要,将不适合用于查询的字段删除掉,包含私有字段、构造函数、get和set属性。
本例中由于领域类Category中仅含一个String类型字段name,所以不必分标准查询和高级查询,所以将用于高级查询的字段“name”删除掉。
本例中,查询文档分类时需指定所属的项目,所以增加一个projectId字段,相应修改带参构造函数和Getter、Setter。Mac操作系统下使用IntelliJ IDEA编码时可以用“Command + N”快捷键:

修改后代码:
package top.cloudev.doc.dto;
import java.io.Serializable;
/**
* Category(文档分类) 的DTO数据传输对象
* Created by Mac.Manon on 2018/04/02
*/
public class CategoryDTO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 关键字(标准查询)
*/
private String keyword;
/**
* 文档分类所属的项目
*/
private Long projectId;
/**
*空构造函数
*
*/
public CategoryDTO(){
}
public CategoryDTO(String keyword, Long projectId) {
this.keyword = keyword;
this.projectId = projectId;
}
/**
*Getter,Setter
*
*/
public String getKeyword() {
return keyword;
}
public void setKeyword(String keyword) {
this.keyword = keyword;
}
public Long getProjectId() {
return projectId;
}
public void setProjectId(Long projectId) {
this.projectId = projectId;
}
}dao层采用JPA接口的方式实现数据查询,根据DTO中字段的调整,修改这里的接口(增加了projectId参数):
修改前代码:
package top.cloudev.doc.dao;
import top.cloudev.doc.domain.Category;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* 领域类 Category(文档分类) 的DAO Repository接口层
* Created by Mac.Manon on 2018/04/02
*/
//@RepositoryRestResource(path = "newpath")
public interface CategoryRepository extends JpaRepository<Category,Long> {
Page<Category> findByIsDeletedFalse(Pageable pageable);
// 标准查询
Page<Category> findByNameContainingAndIsDeletedFalseAllIgnoringCase(String name, Pageable pageable);
}修改后代码:

package top.cloudev.doc.dao;
import top.cloudev.doc.domain.Category;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* 领域类 Category(文档分类) 的DAO Repository接口层
* Created by Mac.Manon on 2018/04/02
*/
//@RepositoryRestResource(path = "newpath")
public interface CategoryRepository extends JpaRepository<Category,Long> {
// 默认列表
Page<Category> findByProjectIdAndIsDeletedFalse(Long projectId, Pageable pageable);
// 标准查询
Page<Category> findByNameContainingAllIgnoringCaseAndProjectIdAndIsDeletedFalse(String name, Long projectId, Pageable pageable);
}由于dao层的查询接口已修改,相应调整服务实现层UserServiceImpl中getPageData方法调用的方法名及参数。这里利用"dto.getProjectId()"给增加的参数传值:

打开文档分类的单元测试类代码,找到"testList()"方法,对其中调用Dao层数据访问接口的代码进行调整(正常情况下应该在“测试无搜索列表”、“测试标准查询”和“测试高级查询”三处有对dao接口的调用,本例中因没有高级查询,所以仅需修改两处):

调整后代码如下:


/**
* 测试无搜索列表
*/
/**---------------------测试用例赋值开始---------------------**/
//TODO 将下面的null值换为测试参数
Pageable pageable=new PageRequest(0,10, Sort.Direction.DESC,"categoryId");
// 期望获得的结果数量(默认有两个测试用例,所以值应为"2L",如果新增了更多测试用例,请相应设定这个值)
expectResultCount = null;
/**---------------------测试用例赋值结束---------------------**/
// 直接通过dao层接口方法获得期望的数据
Page<Category> pagedata = categoryRepository.findByProjectIdAndIsDeletedFalse(c1.getCategoryId(), pageable);
expectData = JsonPath.read(Obj2Json(pagedata),"$").toString();
MvcResult mvcResult = mockMvc
.perform(
MockMvcRequestBuilders.get("/category/list")
.accept(MediaType.APPLICATION_JSON)
)
// 打印结果
.andDo(print())
// 检查状态码为200
.andExpect(status().isOk())
// 检查返回的数据节点
.andExpect(jsonPath("$.pagedata.totalElements").value(expectResultCount))
.andExpect(jsonPath("$.dto.keyword").isEmpty())
.andExpect(jsonPath("$.dto.name").isEmpty())
.andReturn();
// 提取返回结果中的列表数据及翻页信息
responseData = JsonPath.read(mvcResult.getResponse().getContentAsString(),"$.pagedata").toString();
System.out.println("=============无搜索列表期望结果:" + expectData);
System.out.println("=============无搜索列表实际返回:" + responseData);
Assert.assertEquals("错误,无搜索列表返回数据与期望结果有差异",expectData,responseData);
/**
* 测试标准查询
*/
/**---------------------测试用例赋值开始---------------------**/
//TODO 将下面的null值换为测试参数
dto = new CategoryDTO();
dto.setKeyword(null);
dto.setProjectId(c1.getProjectId());
pageable=new PageRequest(0,10, Sort.Direction.DESC,"categoryId");
// 期望获得的结果数量
expectResultCount = null;
/**---------------------测试用例赋值结束---------------------**/
String keyword = dto.getKeyword().trim();
// 直接通过dao层接口方法获得期望的数据
pagedata = categoryRepository.findByNameContainingAllIgnoringCaseAndProjectIdAndIsDeletedFalse(keyword, dto.getProjectId(), pageable);
expectData = JsonPath.read(Obj2Json(pagedata),"$").toString();
mvcResult = mockMvc
.perform(
MockMvcRequestBuilders.get("/category/list")
.param("keyword",dto.getKeyword())
.accept(MediaType.APPLICATION_JSON)
)
// 打印结果
.andDo(print())
// 检查状态码为200
.andExpect(status().isOk())
// 检查返回的数据节点
.andExpect(jsonPath("$.pagedata.totalElements").value(expectResultCount))
.andExpect(jsonPath("$.dto.keyword").value(dto.getKeyword()))
.andExpect(jsonPath("$.dto.name").isEmpty())
.andReturn();
// 提取返回结果中的列表数据及翻页信息
responseData = JsonPath.read(mvcResult.getResponse().getContentAsString(),"$.pagedata").toString();
System.out.println("=============标准查询期望结果:" + expectData);
System.out.println("=============标准查询实际返回:" + responseData);
Assert.assertEquals("错误,标准查询返回数据与期望结果有差异",expectData,responseData);