feat(product): 增加产品列表接口的数据权限测试

- 新增了四个数据权限范围的测试用例:全部数据、本部门数据、本部门及子部门数据、个人数据
- 在 ProductBuilder 中添加了 deptId 和 createId 字段,用于构建测试数据- 修改了 DeviceBuilder 继承自 BaseEntityBuilder,统一基础实体属性
- 在 BaseParam 中添加了 deptId 字段,用于权限控制
- 移除了 Device 实体中的冗余 deptId 字段
This commit is contained in:
zhuangtianxiang 2025-01-21 19:29:17 +08:00
parent 24b7b4093a
commit 0c7301069e
6 changed files with 191 additions and 13 deletions

View File

@ -79,10 +79,6 @@ public class Device extends BaseEntity {
*/
public Long productId;
/**
* 部门ID(权限)
*/
public Long deptId;
/**
* 所属产品

View File

@ -40,4 +40,9 @@ public class BaseParam implements Serializable {
*/
private String remark;
/**
* 部门ID(权限)
*/
public Long deptId;
}

View File

@ -1,9 +1,10 @@
package com.zsc.edu.gateway.domain.iot;
import com.zsc.edu.gateway.domain.system.BaseEntityBuilder;
import com.zsc.edu.gateway.modules.iot.device.entity.Device;
import com.zsc.edu.gateway.modules.system.entity.BaseEntity;
public class DeviceBuilder extends BaseEntity {
public class DeviceBuilder extends BaseEntityBuilder {
private String name;
private Device.Status state = Device.Status.UNACTIVATED;

View File

@ -1,11 +1,13 @@
package com.zsc.edu.gateway.domain.iot;
import com.zsc.edu.gateway.domain.system.BaseEntityBuilder;
import com.zsc.edu.gateway.modules.iot.product.entity.Product;
public class ProductBuilder extends BaseParamBuilder {
public class ProductBuilder extends BaseEntityBuilder {
public String name;
public String productType;
public String model;
public Long deptId;
public Product.LinkType link;
public static ProductBuilder bProduct() {
@ -17,6 +19,16 @@ public class ProductBuilder extends BaseParamBuilder {
return this;
}
public ProductBuilder deptId(Long deptId) {
this.deptId = deptId;
return this;
}
public ProductBuilder createId(Long createId) {
this.createId = createId;
return this;
}
public ProductBuilder productType(String productType) {
this.productType = productType;
return this;
@ -38,6 +50,8 @@ public class ProductBuilder extends BaseParamBuilder {
product.setProductType(productType);
product.setModel(model);
product.setLink(link);
product.setDeptId(deptId);
product.setCreateId(createId);
product.setParams(null);
return product;
}

View File

@ -12,11 +12,13 @@ public class BaseEntityBuilder {
public String remark;
public LocalDateTime createAt;
public LocalDateTime updateAt;
public Long createId;
public BaseEntityBuilder() {
remark = randomAlphabetic(5);
createAt = LocalDateTime.now();
updateAt = LocalDateTime.now();
createId = 1L;
}
}

View File

@ -5,10 +5,14 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zsc.edu.gateway.MockMvcConfigBase;
import com.zsc.edu.gateway.domain.iot.ProductBuilder;
import com.zsc.edu.gateway.framework.mybatisplus.DataScopeType;
import com.zsc.edu.gateway.framework.security.UserDetailsImpl;
import com.zsc.edu.gateway.modules.iot.product.controller.ProductController;
import com.zsc.edu.gateway.modules.iot.product.dto.ProductDto;
import com.zsc.edu.gateway.modules.iot.product.entity.Product;
import com.zsc.edu.gateway.modules.iot.product.service.ProductService;
import com.zsc.edu.gateway.modules.system.entity.Dept;
import com.zsc.edu.gateway.modules.system.entity.Role;
import org.assertj.core.util.Lists;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
@ -19,6 +23,7 @@ import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import java.util.List;
import java.util.Set;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
@ -28,6 +33,7 @@ import static org.springframework.security.test.web.servlet.request.SecurityMock
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@WebMvcTest(ProductController.class)
@ -35,6 +41,8 @@ public class ProductControllerTest extends MockMvcConfigBase {
@Spy
private static Product product1;
private static Product product2;
private static Product product3;
private static Product product4;
@MockBean
private ProductService service;
@ -43,10 +51,14 @@ public class ProductControllerTest extends MockMvcConfigBase {
@BeforeAll
static void beforeAll() {
product1 = ProductBuilder.bProduct().name("Product 1").productType("Description 1").build();
product1 = ProductBuilder.bProduct().name("Product 1").productType("Description 1").deptId(2L).createId(1L).build();
product1.setId(1L);
product2 = ProductBuilder.bProduct().name("Product 2").productType("Description 2").build();
product2 = ProductBuilder.bProduct().name("Product 2").productType("Description 2").deptId(2L).createId(1L).build();
product2.setId(2L);
product3 = ProductBuilder.bProduct().name("Product 3").productType("Description 3").deptId(2L).createId(1L).build();
product3.setId(3L);
product4 = ProductBuilder.bProduct().name("Product 4").productType("Description 4").deptId(3L).createId(2L).build();
product4.setId(4L);
}
@Test
@ -68,13 +80,161 @@ public class ProductControllerTest extends MockMvcConfigBase {
}
@Test
void list() throws Exception {
List<Product> products = Lists.newArrayList(product1, product2);
when(service.page(any(Page.class), any(LambdaQueryWrapper.class))).thenReturn(new Page<Product>().setRecords(products).setTotal((long) products.size()));
mockMvc.perform(get("/api/rest/product").with(user(userDetails)))
void listWithDataScopeALL() throws Exception {
Dept dept = new Dept();
dept.setId(2L);
Role role = new Role();
role.setId(50L);
role.setDataScope(DataScopeType.DATA_SCOPE_ALL);
userDetails.setId(1L);
userDetails.setDept(dept);
userDetails.setRole(role);
userDetails.setDataScopeDeptIds(Set.of(2L));
// 创建测试数据
List<Product> products = Lists.newArrayList(product1, product2, product3, product4);
Page<Product> pageResult = new Page<>();
pageResult.setRecords(products);
pageResult.setTotal(products.size());
// 模拟 service.page 方法的返回值
when(service.page(any(Page.class), any())).thenReturn(pageResult);
// 执行 GET 请求并验证响应
mockMvc.perform(get("/api/rest/product")
.with(user(userDetails)))
.andExpect(status().isOk())
.andExpect(jsonPath("$.records.length()").value(products.size()))
.andExpect(jsonPath("$.total").value(products.size()))
.andExpect(jsonPath("$.records[0].id").value(product1.getId()))
.andExpect(jsonPath("$.records[1].id").value(product2.getId()))
.andExpect(jsonPath("$.records[2].id").value(product3.getId()))
.andExpect(jsonPath("$.records[3].id").value(product4.getId()))
.andExpect(jsonPath("$.records[0].deptId").value(2L))
.andExpect(jsonPath("$.records[1].deptId").value(2L))
.andExpect(jsonPath("$.records[2].deptId").value(2L))
.andExpect(jsonPath("$.records[3].deptId").value(3L))
.andExpect(jsonPath("$.records[0].createId").value(1L))
.andExpect(jsonPath("$.records[1].createId").value(1L))
.andExpect(jsonPath("$.records[2].createId").value(1L))
.andExpect(jsonPath("$.records[3].createId").value(2L))
.andDo(print());
verify(service).page(any(Page.class), any(LambdaQueryWrapper.class));
// 验证 service.page 方法确实被调用了一次
verify(service).page(any(Page.class), any());
}
@Test
void listWithDataScopeDept() throws Exception {
Dept dept = new Dept();
dept.setId(2L);
Role role = new Role();
role.setId(50L);
role.setDataScope(DataScopeType.DATA_SCOPE_DEPT);
userDetails.setId(1L);
userDetails.setDept(dept);
userDetails.setRole(role);
userDetails.setDataScopeDeptIds(Set.of(2L));
// 创建测试数据
List<Product> products = Lists.newArrayList(product1, product2, product3);
Page<Product> pageResult = new Page<>();
pageResult.setRecords(products);
pageResult.setTotal(products.size());
// 模拟 service.page 方法的返回值
when(service.page(any(Page.class), any())).thenReturn(pageResult);
// 执行 GET 请求并验证响应
mockMvc.perform(get("/api/rest/product")
.with(user(userDetails)))
.andExpect(status().isOk())
.andExpect(jsonPath("$.records.length()").value(products.size()))
.andExpect(jsonPath("$.total").value(products.size()))
.andExpect(jsonPath("$.records[0].id").value(product1.getId()))
.andExpect(jsonPath("$.records[1].id").value(product2.getId()))
.andExpect(jsonPath("$.records[2].id").value(product3.getId()))
.andExpect(jsonPath("$.records[0].deptId").value(2L))
.andExpect(jsonPath("$.records[1].deptId").value(2L))
.andExpect(jsonPath("$.records[2].deptId").value(2L))
.andExpect(jsonPath("$.records[0].createId").value(1L))
.andExpect(jsonPath("$.records[1].createId").value(1L))
.andExpect(jsonPath("$.records[2].createId").value(1L))
.andDo(print());
// 验证 service.page 方法确实被调用了一次
verify(service).page(any(Page.class), any());
}
@Test
void listWithDataScopeDeptAndChild() throws Exception {
Dept dept = new Dept();
dept.setId(2L);
Role role = new Role();
role.setId(50L);
role.setDataScope(DataScopeType.DATA_SCOPE_DEPT_AND_CHILD);
userDetails.setId(1L);
userDetails.setDept(dept);
userDetails.setRole(role);
userDetails.setDataScopeDeptIds(Set.of(2L));
// 创建测试数据
List<Product> products = Lists.newArrayList(product1, product2, product3, product4);
Page<Product> pageResult = new Page<>();
pageResult.setRecords(products);
pageResult.setTotal(products.size());
// 模拟 service.page 方法的返回值
when(service.page(any(Page.class), any())).thenReturn(pageResult);
// 执行 GET 请求并验证响应
mockMvc.perform(get("/api/rest/product")
.with(user(userDetails)))
.andExpect(status().isOk())
.andExpect(jsonPath("$.records.length()").value(products.size()))
.andExpect(jsonPath("$.total").value(products.size()))
.andExpect(jsonPath("$.records[0].id").value(product1.getId()))
.andExpect(jsonPath("$.records[1].id").value(product2.getId()))
.andExpect(jsonPath("$.records[2].id").value(product3.getId()))
.andExpect(jsonPath("$.records[3].id").value(product4.getId()))
.andExpect(jsonPath("$.records[0].deptId").value(2L))
.andExpect(jsonPath("$.records[1].deptId").value(2L))
.andExpect(jsonPath("$.records[2].deptId").value(2L))
.andExpect(jsonPath("$.records[3].deptId").value(3L))
.andExpect(jsonPath("$.records[0].createId").value(1L))
.andExpect(jsonPath("$.records[1].createId").value(1L))
.andExpect(jsonPath("$.records[2].createId").value(1L))
.andExpect(jsonPath("$.records[3].createId").value(2L))
.andDo(print());
// 验证 service.page 方法确实被调用了一次
verify(service).page(any(Page.class), any());
}
@Test
void listWithDataScopeSelf() throws Exception {
Dept dept = new Dept();
dept.setId(2L);
Role role = new Role();
role.setId(50L);
role.setDataScope(DataScopeType.DATA_SCOPE_SELF);
userDetails.setId(1L);
userDetails.setDept(dept);
userDetails.setRole(role);
userDetails.setDataScopeDeptIds(Set.of(2L));
// 创建测试数据
List<Product> products = Lists.newArrayList(product1, product2, product3);
Page<Product> pageResult = new Page<>();
pageResult.setRecords(products);
pageResult.setTotal(products.size());
// 模拟 service.page 方法的返回值
when(service.page(any(Page.class), any())).thenReturn(pageResult);
// 执行 GET 请求并验证响应
mockMvc.perform(get("/api/rest/product")
.with(user(userDetails)))
.andExpect(status().isOk())
.andExpect(jsonPath("$.records.length()").value(products.size()))
.andExpect(jsonPath("$.total").value(products.size()))
.andExpect(jsonPath("$.records[0].id").value(product1.getId()))
.andExpect(jsonPath("$.records[1].id").value(product2.getId()))
.andExpect(jsonPath("$.records[2].id").value(product3.getId()))
.andExpect(jsonPath("$.records[0].deptId").value(2L))
.andExpect(jsonPath("$.records[1].deptId").value(2L))
.andExpect(jsonPath("$.records[2].deptId").value(2L))
.andExpect(jsonPath("$.records[0].createId").value(1L))
.andExpect(jsonPath("$.records[1].createId").value(1L))
.andExpect(jsonPath("$.records[2].createId").value(1L))
.andDo(print());
// 验证 service.page 方法确实被调用了一次
verify(service).page(any(Page.class), any());
}
@Test