浏览代码

test: 新增成长规划师模块测试用例

- GuideFamilyTaskControllerTest:路由映射和权限测试
- GuideOrderControllerTest:订单列表和统计测试
- GuideTeamControllerTest:团队管理测试
- GuideApplicationServiceTest:申请审核测试
- GuideFamilyServiceTest:家庭绑定测试
- GuideHierarchyServiceTest:层级关系测试
- GuidePackageServiceTest:套餐管理测试

Ultraworked with Sisyphus

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
User 4 月之前
父节点
当前提交
c0745bbdf3

+ 215 - 8
zxyj-backend/src/test/java/com/zxyj/controller/GuideFamilyTaskControllerTest.java

@@ -1,22 +1,26 @@
 package com.zxyj.controller;
 
-import javax.annotation.Resource;
-
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.zxyj.common.Result;
 import com.zxyj.controller.guide.GuideFamilyTaskController;
-import com.zxyj.service.TaskService;
+import com.zxyj.dto.TaskReviewDTO;
+import com.zxyj.entity.Child;
+import com.zxyj.entity.Task;
+import com.zxyj.entity.User;
 import com.zxyj.mapper.ChildMapper;
-import com.zxyj.mapper.UserMapper;
 import com.zxyj.mapper.TaskMapper;
+import com.zxyj.mapper.UserMapper;
+import com.zxyj.service.TaskService;
 import org.junit.jupiter.api.Test;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.boot.test.mock.mockito.MockBean;
 
-import java.util.Collections;
-import java.util.List;
+import javax.annotation.Resource;
+import java.util.*;
 
 import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.when;
 
 @SpringBootTest
@@ -37,6 +41,37 @@ public class GuideFamilyTaskControllerTest {
     @MockBean
     private TaskMapper taskMapper;
 
+    private User mockUser(Long id, String role, String nickname) {
+        User user = new User();
+        user.setId(id);
+        user.setRole(role);
+        user.setNickname(nickname);
+        return user;
+    }
+
+    private Child mockChild(Long id, Long familyId, String nickname) {
+        Child child = new Child();
+        child.setId(id);
+        child.setFamilyId(familyId);
+        child.setNickname(nickname);
+        child.setTotalPoints(100);
+        child.setStreakDays(5);
+        return child;
+    }
+
+    private Task mockTask(Long id, Long childId, Long familyId, String status) {
+        Task task = new Task();
+        task.setId(id);
+        task.setChildId(childId);
+        task.setFamilyId(familyId);
+        task.setTitle("测试任务" + id);
+        task.setStatus(status);
+        task.setPoints(10);
+        return task;
+    }
+
+    // --- Existing tests ---
+
     @Test
     public void getBoundFamilies_TeacherRole_Success() {
         when(userMapper.selectList(any())).thenReturn(Collections.emptyList());
@@ -49,4 +84,176 @@ public class GuideFamilyTaskControllerTest {
         Result<?> result = controller.getBoundFamilies(2L, "parent");
         assertNotNull(result);
     }
-}
+
+    // --- New tests ---
+
+    @Test
+    public void getBoundFamilies_WithFamilies() {
+        Long guideId = 1L;
+        User guide = mockUser(guideId, "teacher", "指导师");
+        guide.setTeacherFamilyIds("100,101");
+        when(userMapper.selectById(guideId)).thenReturn(guide);
+
+        User parent = mockUser(10L, "parent", "家长");
+        when(userMapper.selectList(any(QueryWrapper.class))).thenReturn(Collections.singletonList(parent));
+
+        Child child = mockChild(20L, 100L, "孩子");
+        when(childMapper.selectList(any(QueryWrapper.class))).thenReturn(Collections.singletonList(child));
+        when(taskService.getPendingReviewTasksForChild(20L)).thenReturn(new ArrayList<>());
+
+        @SuppressWarnings("unchecked")
+        Result<List<Map<String, Object>>> result = (Result<List<Map<String, Object>>>) (Result<?>) controller.getBoundFamilies(guideId, "teacher");
+        assertNotNull(result);
+        assertEquals(200, result.getCode());
+    }
+
+    @Test
+    public void getFamilyTaskOverview_WithChildren() {
+        Long guideId = 1L;
+        Long familyId = 100L;
+        Child child = mockChild(20L, familyId, "孩子A");
+        when(childMapper.selectList(any(QueryWrapper.class))).thenReturn(Collections.singletonList(child));
+        when(taskService.getTodayTasks(20L)).thenReturn(new ArrayList<>());
+        when(taskService.getPendingReviewTasksForChild(20L)).thenReturn(new ArrayList<>());
+        when(taskService.getAllTasksByChild(20L)).thenReturn(new ArrayList<>());
+
+        Result<Map<String, Object>> result = controller.getFamilyTaskOverview(guideId, "teacher", familyId);
+        Map<String, Object> data = result.getData();
+        assertNotNull(data);
+        assertEquals(familyId, data.get("familyId"));
+        assertEquals(1, data.get("totalChildren"));
+    }
+
+    @Test
+    public void getFamilyTaskOverview_NonTeacher_AccessDenied() {
+        Result<Map<String, Object>> result = controller.getFamilyTaskOverview(1L, "parent", 100L);
+        assertEquals("Access denied", result.getMessage());
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void getChildTasks_WithPagination() {
+        Long familyId = 100L;
+        Long childId = 20L;
+        List<Task> tasks = Arrays.asList(
+            mockTask(1L, childId, familyId, "pending"),
+            mockTask(2L, childId, familyId, "completed")
+        );
+        Page<Task> taskPage = new Page<>(1, 10);
+        taskPage.setRecords(tasks);
+        taskPage.setTotal(2);
+
+        when(taskService.getTaskHistoryByChild(eq(childId), eq(1), eq(10), eq(null))).thenReturn(taskPage);
+
+        Map<String, Object> params = new HashMap<>();
+        params.put("page", 1);
+        params.put("size", 10);
+
+        Result<Page<Task>> result = controller.getChildTasks(familyId, childId, "teacher", params);
+        Page<Task> page = result.getData();
+        assertEquals(2, page.getTotal());
+        assertEquals(2, page.getRecords().size());
+    }
+
+    @Test
+    public void getPendingReviewTasks_Success() {
+        Long familyId = 100L;
+        Long childId = 20L;
+        List<Task> pendingTasks = Collections.singletonList(
+            mockTask(5L, childId, familyId, "pending_review")
+        );
+        when(taskService.getPendingReviewTasksForChild(childId)).thenReturn(pendingTasks);
+
+        Result<List<Task>> result = controller.getPendingReviewTasks(familyId, childId, "teacher");
+        assertEquals(1, result.getData().size());
+    }
+
+    @Test
+    public void reviewTask_Success() {
+        Long familyId = 100L;
+        Long taskId = 1L;
+        TaskReviewDTO dto = new TaskReviewDTO();
+        dto.setApproved(true);
+        dto.setComment("做得好");
+
+        when(taskService.reviewTask(eq(taskId), any(TaskReviewDTO.class))).thenReturn(true);
+
+        Result<Boolean> result = controller.reviewTask(familyId, taskId, "teacher", dto);
+        assertTrue(result.getData());
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void batchReviewTasks_Success() {
+        Long familyId = 100L;
+        List<Long> taskIds = Arrays.asList(1L, 2L, 3L);
+        Map<String, Object> params = new HashMap<>();
+        params.put("taskIds", taskIds);
+        params.put("approved", true);
+
+        when(taskService.reviewTask(anyLong(), any(TaskReviewDTO.class))).thenReturn(true);
+
+        Result<Map<String, Object>> result = controller.batchReviewTasks(familyId, "teacher", params);
+        Map<String, Object> data = result.getData();
+        assertEquals(3, data.get("successCount"));
+        assertEquals(0, data.get("failCount"));
+    }
+
+    @Test
+    public void updateTask_Success() {
+        Long familyId = 100L;
+        Long taskId = 1L;
+        Task task = mockTask(taskId, 20L, familyId, "pending");
+        when(taskMapper.selectById(taskId)).thenReturn(task);
+        when(taskMapper.updateById(any(Task.class))).thenReturn(1);
+
+        Map<String, Object> taskData = new HashMap<>();
+        taskData.put("title", "新标题");
+        taskData.put("description", "新描述");
+        taskData.put("points", 20);
+
+        Result<Boolean> result = controller.updateTask(familyId, taskId, "teacher", taskData);
+        assertTrue(result.getData());
+    }
+
+    @Test
+    public void updateTask_NotFound_ReturnsError() {
+        when(taskMapper.selectById(999L)).thenReturn(null);
+
+        Map<String, Object> taskData = new HashMap<>();
+        taskData.put("title", "新标题");
+        Result<Boolean> result = controller.updateTask(100L, 999L, "teacher", taskData);
+        assertEquals("任务不存在", result.getMessage());
+    }
+
+    @Test
+    public void updateTask_WrongFamily_ReturnsError() {
+        Long taskId = 1L;
+        Task task = mockTask(taskId, 20L, 999L, "pending"); // different familyId
+        when(taskMapper.selectById(taskId)).thenReturn(task);
+
+        Map<String, Object> taskData = new HashMap<>();
+        taskData.put("title", "新标题");
+        Result<Boolean> result = controller.updateTask(100L, taskId, "teacher", taskData);
+        assertEquals("任务不属于该家庭", result.getMessage());
+    }
+
+    @Test
+    public void deleteTask_Success() {
+        Long familyId = 100L;
+        Long taskId = 1L;
+        Task task = mockTask(taskId, 20L, familyId, "pending");
+        when(taskMapper.selectById(taskId)).thenReturn(task);
+        when(taskMapper.updateById(any(Task.class))).thenReturn(1);
+
+        Result<Boolean> result = controller.deleteTask(familyId, taskId, "teacher");
+        assertTrue(result.getData());
+    }
+
+    @Test
+    public void deleteTask_NotFound_ReturnsError() {
+        when(taskMapper.selectById(999L)).thenReturn(null);
+        Result<Boolean> result = controller.deleteTask(100L, 999L, "teacher");
+        assertEquals("任务不存在", result.getMessage());
+    }
+}

+ 173 - 0
zxyj-backend/src/test/java/com/zxyj/controller/GuideOrderControllerTest.java

@@ -0,0 +1,173 @@
+package com.zxyj.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.zxyj.common.Result;
+import com.zxyj.controller.guide.GuideOrderController;
+import com.zxyj.entity.PackageOrder;
+import com.zxyj.mapper.PackageOrderMapper;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.util.*;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.when;
+
+@SpringBootTest
+public class GuideOrderControllerTest {
+
+    @Resource
+    private GuideOrderController controller;
+
+    @MockBean
+    private PackageOrderMapper packageOrderMapper;
+
+    private PackageOrder mockOrder(Long id, Long guideId, String status) {
+        PackageOrder order = new PackageOrder();
+        order.setId(id);
+        order.setOrderNo("ORD" + id);
+        order.setUserId(100L);
+        order.setFamilyId(200L);
+        order.setPackageId(300L);
+        order.setPackageName("测试套餐");
+        order.setPrice(new BigDecimal("199.00"));
+        order.setGuideId(guideId);
+        order.setStatus(status);
+        order.setCreatedAt(new Date());
+        return order;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void getOrders_WithPagination() {
+        Long guideId = 1L;
+        List<PackageOrder> records = Arrays.asList(
+            mockOrder(1L, guideId, "paid"),
+            mockOrder(2L, guideId, "paid")
+        );
+        Page<PackageOrder> page = new Page<>(1, 10);
+        page.setRecords(records);
+        page.setTotal(2);
+        page.setPages(1);
+        page.setCurrent(1);
+
+        when(packageOrderMapper.selectPage(any(Page.class), any(LambdaQueryWrapper.class))).thenReturn(page);
+
+        Map<String, Object> params = new HashMap<>();
+        params.put("page", 1);
+        params.put("size", 10);
+
+        Result<Map<String, Object>> result = controller.getOrders(guideId, params);
+        assertNotNull(result);
+        assertEquals(200, result.getCode());
+        Map<String, Object> data = result.getData();
+        assertEquals(2L, data.get("total"));
+        assertEquals(1L, data.get("pages"));
+        assertEquals(1L, data.get("current"));
+        List<PackageOrder> resultRecords = (List<PackageOrder>) data.get("records");
+        assertEquals(2, resultRecords.size());
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void getOrders_WithStatusFilter() {
+        Long guideId = 1L;
+        List<PackageOrder> records = Collections.singletonList(
+            mockOrder(3L, guideId, "pending")
+        );
+        Page<PackageOrder> page = new Page<>(1, 10);
+        page.setRecords(records);
+        page.setTotal(1);
+
+        when(packageOrderMapper.selectPage(any(Page.class), any(LambdaQueryWrapper.class))).thenReturn(page);
+
+        Map<String, Object> params = new HashMap<>();
+        params.put("status", "pending");
+
+        Result<Map<String, Object>> result = controller.getOrders(guideId, params);
+        Map<String, Object> data = result.getData();
+        assertEquals(1L, data.get("total"));
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void getOrders_NullParams() {
+        Long guideId = 1L;
+        Page<PackageOrder> emptyPage = new Page<>(1, 10);
+        emptyPage.setRecords(new ArrayList<>());
+        emptyPage.setTotal(0);
+
+        when(packageOrderMapper.selectPage(any(Page.class), any(LambdaQueryWrapper.class))).thenReturn(emptyPage);
+
+        Result<Map<String, Object>> result = controller.getOrders(guideId, null);
+        Map<String, Object> data = result.getData();
+        assertNotNull(data);
+        assertEquals(0L, data.get("total"));
+    }
+
+    @Test
+    public void getOrderStats_WithData() {
+        Long guideId = 1L;
+        List<PackageOrder> paidOrders = Arrays.asList(
+            mockOrder(4L, guideId, "paid"),
+            mockOrder(5L, guideId, "paid")
+        );
+        // Ensure prices are set for the paid orders
+        paidOrders.get(0).setPrice(new BigDecimal("100.00"));
+        paidOrders.get(1).setPrice(new BigDecimal("200.00"));
+
+        when(packageOrderMapper.selectCount(any(LambdaQueryWrapper.class))).thenReturn(3L, 2L);
+        when(packageOrderMapper.selectList(any(LambdaQueryWrapper.class))).thenReturn(paidOrders);
+
+        Result<Map<String, Object>> result = controller.getOrderStats(guideId);
+        Map<String, Object> stats = result.getData();
+        assertEquals(3L, stats.get("totalOrders"));
+        assertEquals(2L, stats.get("paidOrders"));
+        assertEquals(new BigDecimal("300.00"), stats.get("totalRevenue"));
+        assertEquals(1L, stats.get("pendingOrders"));
+    }
+
+    @Test
+    public void getOrderDetail_Success() {
+        Long guideId = 1L;
+        PackageOrder order = mockOrder(10L, guideId, "paid");
+        when(packageOrderMapper.selectById(10L)).thenReturn(order);
+
+        Map<String, Object> params = Collections.singletonMap("id", 10);
+        Result<PackageOrder> result = controller.getOrderDetail(guideId, params);
+        assertEquals(200, result.getCode());
+        assertEquals(10L, result.getData().getId());
+    }
+
+    @Test
+    public void getOrderDetail_NotFound() {
+        when(packageOrderMapper.selectById(999L)).thenReturn(null);
+
+        Map<String, Object> params = Collections.singletonMap("id", 999);
+        Result<PackageOrder> result = controller.getOrderDetail(1L, params);
+        assertEquals("订单不存在", result.getMessage());
+    }
+
+    @Test
+    public void getOrderDetail_WrongGuide() {
+        Long guideId = 1L;
+        PackageOrder order = mockOrder(11L, 999L, "paid");
+        when(packageOrderMapper.selectById(11L)).thenReturn(order);
+
+        Map<String, Object> params = Collections.singletonMap("id", 11);
+        Result<PackageOrder> result = controller.getOrderDetail(guideId, params);
+        assertEquals("无权查看", result.getMessage());
+    }
+
+    @Test
+    public void getOrderDetail_MissingId() {
+        Map<String, Object> params = new HashMap<>();
+        Result<PackageOrder> result = controller.getOrderDetail(1L, params);
+        assertEquals("缺少订单ID", result.getMessage());
+    }
+}

+ 184 - 0
zxyj-backend/src/test/java/com/zxyj/controller/GuideTeamControllerTest.java

@@ -0,0 +1,184 @@
+package com.zxyj.controller;
+
+import javax.annotation.Resource;
+
+import com.zxyj.common.Result;
+import com.zxyj.controller.guide.GuideTeamController;
+import com.zxyj.entity.GuideInviteCode;
+import com.zxyj.entity.User;
+import com.zxyj.mapper.UserMapper;
+import com.zxyj.service.GuideInviteCodeService;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.boot.test.mock.mockito.SpyBean;
+
+import java.util.*;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+
+/**
+ * 成长规划师-团队管理控制器测试
+ * 覆盖场景:团队查询、邀请码管理、成员列表、统计
+ */
+@SpringBootTest
+public class GuideTeamControllerTest {
+
+    @Resource
+    private GuideTeamController controller;
+
+    @MockBean
+    private GuideInviteCodeService guideInviteCodeService;
+
+    @MockBean
+    private UserMapper userMapper;
+
+    private GuideInviteCode mockInviteCode(Long guideId) {
+        GuideInviteCode code = new GuideInviteCode();
+        code.setId(1L);
+        code.setGuideId(guideId);
+        code.setCode("TESTCODE");
+        code.setStatus("active");
+        code.setUseCount(3);
+        code.setMaxUseCount(100);
+        return code;
+    }
+
+    private User mockUser(Long id, String nickname) {
+        User user = new User();
+        user.setId(id);
+        user.setNickname(nickname);
+        user.setRole("teacher");
+        return user;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testGetMyTeam_WithMembers() {
+        Long guideId = 1L;
+        GuideInviteCode inviteCode = mockInviteCode(guideId);
+
+        when(guideInviteCodeService.getByGuideId(guideId)).thenReturn(inviteCode);
+        List<User> mockMembers = Arrays.asList(
+            mockUser(2L, "成员A"),
+            mockUser(3L, "成员B"));
+        when(userMapper.selectList(any())).thenReturn(mockMembers);
+
+        Result<Map<String, Object>> result = controller.getMyTeam(guideId);
+        assertNotNull(result);
+        assertEquals(200, result.getCode());
+
+        Map<String, Object> data = result.getData();
+        assertNotNull(data);
+        assertEquals(2, data.get("memberCount"));
+        assertEquals(inviteCode, data.get("inviteCode"));
+
+        List<User> members = (List<User>) data.get("members");
+        assertEquals(2, members.size());
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testGetMyTeam_NoInviteCode() {
+        Long guideId = 99L;
+        when(guideInviteCodeService.getByGuideId(guideId)).thenReturn(null);
+
+        Result<Map<String, Object>> result = controller.getMyTeam(guideId);
+        assertNotNull(result);
+
+        Map<String, Object> data = result.getData();
+        assertEquals(0, data.get("memberCount"));
+    }
+
+    @Test
+    public void testGetMyInviteCode_Existing() {
+        Long guideId = 1L;
+        GuideInviteCode existing = mockInviteCode(guideId);
+        when(guideInviteCodeService.getByGuideId(guideId)).thenReturn(existing);
+
+        Result<GuideInviteCode> result = controller.getMyInviteCode(guideId);
+        assertNotNull(result);
+        assertEquals(existing, result.getData());
+    }
+
+    @Test
+    public void testGetMyInviteCode_CreateNew() {
+        Long guideId = 2L;
+        when(guideInviteCodeService.getByGuideId(guideId)).thenReturn(null);
+        GuideInviteCode newCode = mockInviteCode(guideId);
+        when(guideInviteCodeService.createInviteCode(guideId)).thenReturn(newCode);
+
+        Result<GuideInviteCode> result = controller.getMyInviteCode(guideId);
+        assertNotNull(result);
+        assertEquals(newCode, result.getData());
+    }
+
+    @Test
+    public void testGenerateInviteCode() {
+        Long guideId = 1L;
+        GuideInviteCode newCode = mockInviteCode(guideId);
+        newCode.setCode("NEWCODE");
+        when(guideInviteCodeService.createInviteCode(guideId)).thenReturn(newCode);
+
+        Result<GuideInviteCode> result = controller.generateInviteCode(guideId);
+        assertNotNull(result);
+        assertEquals("NEWCODE", result.getData().getCode());
+    }
+
+    @Test
+    public void testGetTeamMembers_WithData() {
+        Long guideId = 1L;
+        GuideInviteCode inviteCode = mockInviteCode(guideId);
+        when(guideInviteCodeService.getByGuideId(guideId)).thenReturn(inviteCode);
+
+        List<User> members = Arrays.asList(mockUser(2L, "成员A"));
+        when(userMapper.selectList(any())).thenReturn(members);
+
+        Result<List<User>> result = controller.getTeamMembers(guideId);
+        assertNotNull(result);
+        assertEquals(1, result.getData().size());
+    }
+
+    @Test
+    public void testGetTeamMembers_NoInviteCode() {
+        Long guideId = 99L;
+        when(guideInviteCodeService.getByGuideId(guideId)).thenReturn(null);
+
+        Result<List<User>> result = controller.getTeamMembers(guideId);
+        assertNotNull(result);
+        assertTrue(result.getData().isEmpty());
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testGetTeamStats_WithMembers() {
+        Long guideId = 1L;
+        GuideInviteCode inviteCode = mockInviteCode(guideId);
+        when(guideInviteCodeService.getByGuideId(guideId)).thenReturn(inviteCode);
+
+        List<User> members = Arrays.asList(
+            mockUser(2L, "成员A"),
+            mockUser(3L, "成员B"),
+            mockUser(4L, "成员C"));
+        when(userMapper.selectList(any())).thenReturn(members);
+
+        Result<Map<String, Object>> result = controller.getTeamStats(guideId);
+        Map<String, Object> stats = result.getData();
+        assertEquals(3, stats.get("totalMembers"));
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testGetTeamStats_NoInviteCode() {
+        Long guideId = 99L;
+        when(guideInviteCodeService.getByGuideId(guideId)).thenReturn(null);
+
+        Result<Map<String, Object>> result = controller.getTeamStats(guideId);
+        Map<String, Object> stats = result.getData();
+        assertEquals(0, stats.get("totalMembers"));
+        assertEquals(0, stats.get("totalFamilies"));
+        assertEquals(0, stats.get("totalChildren"));
+    }
+}

+ 117 - 0
zxyj-backend/src/test/java/com/zxyj/service/GuideApplicationServiceTest.java

@@ -0,0 +1,117 @@
+package com.zxyj.service;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.zxyj.entity.GuideApplication;
+import com.zxyj.mapper.GuideApplicationMapper;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+
+import javax.annotation.Resource;
+import java.util.*;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+@SpringBootTest
+public class GuideApplicationServiceTest {
+
+    @Resource
+    private GuideApplicationService guideApplicationService;
+
+    @MockBean
+    private GuideApplicationMapper guideApplicationMapper;
+
+    private GuideApplication createApplication(Long id, Long userId, String type, String status) {
+        GuideApplication app = new GuideApplication();
+        app.setId(id);
+        app.setUserId(userId);
+        app.setType(type);
+        app.setStatus(status);
+        app.setCreatedAt(new Date());
+        return app;
+    }
+
+    @Test
+    public void applyNew_Success() {
+        when(guideApplicationMapper.insert(any(GuideApplication.class))).thenReturn(1);
+
+        boolean result = guideApplicationService.applyNew(1L, "junior", 100L, "proof.jpg");
+        assertTrue(result);
+    }
+
+    @Test
+    public void applyUpgrade_Success() {
+        when(guideApplicationMapper.insert(any(GuideApplication.class))).thenReturn(1);
+
+        boolean result = guideApplicationService.applyUpgrade(1L, "junior", "senior", "proof.jpg");
+        assertTrue(result);
+    }
+
+    @Test
+    public void getPendingApplications_WithData() {
+        List<GuideApplication> apps = Arrays.asList(
+            createApplication(1L, 1L, "new_apply", "pending"),
+            createApplication(2L, 2L, "upgrade", "pending")
+        );
+        when(guideApplicationMapper.selectList(any(LambdaQueryWrapper.class))).thenReturn(apps);
+
+        List<GuideApplication> result = guideApplicationService.getPendingApplications();
+        assertNotNull(result);
+        assertEquals(2, result.size());
+        assertTrue(result.stream().allMatch(a -> "pending".equals(a.getStatus())));
+    }
+
+    @Test
+    public void getPendingApplications_NoData() {
+        when(guideApplicationMapper.selectList(any(LambdaQueryWrapper.class))).thenReturn(new ArrayList<>());
+
+        List<GuideApplication> result = guideApplicationService.getPendingApplications();
+        assertNotNull(result);
+        assertTrue(result.isEmpty());
+    }
+
+    @Test
+    public void approveApplication_Success() {
+        GuideApplication app = createApplication(1L, 1L, "new_apply", "pending");
+        when(guideApplicationMapper.selectById(1L)).thenReturn(app);
+        when(guideApplicationMapper.updateById(any(GuideApplication.class))).thenReturn(1);
+
+        boolean result = guideApplicationService.approveApplication(1L, 100L);
+        assertTrue(result);
+        assertEquals("approved", app.getStatus());
+        assertEquals(100L, app.getReviewedBy());
+        assertNotNull(app.getReviewedAt());
+    }
+
+    @Test
+    public void approveApplication_NotFound_ReturnsFalse() {
+        when(guideApplicationMapper.selectById(999L)).thenReturn(null);
+
+        boolean result = guideApplicationService.approveApplication(999L, 100L);
+        assertFalse(result);
+    }
+
+    @Test
+    public void rejectApplication_Success() {
+        GuideApplication app = createApplication(1L, 1L, "new_apply", "pending");
+        when(guideApplicationMapper.selectById(1L)).thenReturn(app);
+        when(guideApplicationMapper.updateById(any(GuideApplication.class))).thenReturn(1);
+
+        boolean result = guideApplicationService.rejectApplication(1L, 100L, "资料不完整");
+        assertTrue(result);
+        assertEquals("rejected", app.getStatus());
+        assertEquals("资料不完整", app.getRejectReason());
+        assertEquals(100L, app.getReviewedBy());
+        assertNotNull(app.getReviewedAt());
+    }
+
+    @Test
+    public void rejectApplication_NotFound_ReturnsFalse() {
+        when(guideApplicationMapper.selectById(999L)).thenReturn(null);
+
+        boolean result = guideApplicationService.rejectApplication(999L, 100L, "原因");
+        assertFalse(result);
+    }
+}

+ 140 - 0
zxyj-backend/src/test/java/com/zxyj/service/GuideFamilyServiceTest.java

@@ -0,0 +1,140 @@
+package com.zxyj.service;
+import javax.annotation.Resource;
+
+import com.zxyj.entity.GuideFamily;
+import com.zxyj.mapper.GuideFamilyMapper;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * 成长规划师-家庭管理服务测试
+ * 覆盖场景:绑定token生成、确认绑定、解除绑定、绑定状态查询
+ */
+@SpringBootTest
+@Transactional
+public class GuideFamilyServiceTest {
+
+    @Resource
+    private GuideFamilyService guideFamilyService;
+
+    @Resource
+    private GuideFamilyMapper guideFamilyMapper;
+
+    @BeforeEach
+    public void cleanupTestData() {
+        // 清理之前的测试残留数据,避免唯一键冲突
+        for (long id = 99901L; id <= 99905L; id++) {
+            guideFamilyMapper.delete(
+                new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<GuideFamily>()
+                    .eq("guide_id", id)
+                    .eq("family_id", id)
+            );
+        }
+    }
+
+    @Test
+    public void testGenerateBindToken() {
+        Long guideId = 99901L;
+        Long familyId = 99901L;
+
+        String token = guideFamilyService.generateBindToken(guideId, familyId);
+        assertNotNull(token);
+        assertEquals(16, token.length());
+
+        List<GuideFamily> families = guideFamilyService.getFamiliesByGuide(guideId);
+        boolean found = families.stream().anyMatch(f ->
+            f.getFamilyId().equals(familyId) && "binding".equals(f.getStatus()));
+        assertTrue(found);
+    }
+
+    @Test
+    public void testConfirmBind_CreateNew() {
+        Long guideId = 99902L;
+        Long familyId = 99902L;
+
+        boolean result = guideFamilyService.confirmBind(guideId, familyId,
+            "monthly", new BigDecimal("199.00"));
+        assertTrue(result);
+
+        assertTrue(guideFamilyService.isBound(guideId, familyId));
+
+        List<GuideFamily> byGuide = guideFamilyService.getFamiliesByGuide(guideId);
+        assertFalse(byGuide.isEmpty());
+    }
+
+    @Test
+    public void testConfirmBind_UpdateExisting() {
+        Long guideId = 99903L;
+        Long familyId = 99903L;
+
+        guideFamilyService.confirmBind(guideId, familyId,
+            "monthly", new BigDecimal("199.00"));
+
+        boolean updated = guideFamilyService.confirmBind(guideId, familyId,
+            "yearly", new BigDecimal("1999.00"));
+        assertTrue(updated);
+
+        List<GuideFamily> families = guideFamilyService.getFamiliesByGuide(guideId);
+        GuideFamily gf = families.stream()
+            .filter(f -> f.getFamilyId().equals(familyId))
+            .findFirst().orElse(null);
+        assertNotNull(gf);
+        assertEquals("yearly", gf.getServiceType());
+        assertEquals(0, new BigDecimal("1999.00").compareTo(gf.getServicePrice()));
+    }
+
+    @Test
+    public void testUnbind() {
+        Long guideId = 99904L;
+        Long familyId = 99904L;
+
+        guideFamilyService.confirmBind(guideId, familyId,
+            "consulting", new BigDecimal("99.00"));
+
+        List<GuideFamily> before = guideFamilyService.getFamiliesByGuide(guideId);
+        assertFalse(before.isEmpty());
+
+        GuideFamily gf = before.stream()
+            .filter(f -> f.getFamilyId().equals(familyId))
+            .findFirst().orElse(null);
+        assertNotNull(gf);
+
+        boolean unbindResult = guideFamilyService.unbind(gf.getId());
+        assertTrue(unbindResult);
+
+        assertFalse(guideFamilyService.isBound(guideId, familyId));
+    }
+
+    @Test
+    public void testIsBound_NoBinding_ReturnsFalse() {
+        boolean bound = guideFamilyService.isBound(99999L, 99999L);
+        assertFalse(bound);
+    }
+
+    @Test
+    public void testGetFamiliesByGuide_NoData() {
+        List<GuideFamily> families = guideFamilyService.getFamiliesByGuide(99998L);
+        assertNotNull(families);
+        assertTrue(families.isEmpty());
+    }
+
+    @Test
+    public void testGetGuidesByFamily() {
+        Long guideId = 99905L;
+        Long familyId = 99905L;
+
+        guideFamilyService.confirmBind(guideId, familyId,
+            "monthly", new BigDecimal("199.00"));
+
+        List<GuideFamily> guides = guideFamilyService.getGuidesByFamily(familyId);
+        assertFalse(guides.isEmpty());
+        assertTrue(guides.stream().anyMatch(g -> g.getGuideId().equals(guideId)));
+    }
+}

+ 193 - 0
zxyj-backend/src/test/java/com/zxyj/service/GuideHierarchyServiceTest.java

@@ -0,0 +1,193 @@
+package com.zxyj.service;
+import javax.annotation.Resource;
+
+import com.zxyj.entity.GuideHierarchy;
+import com.zxyj.entity.User;
+import com.zxyj.mapper.GuideHierarchyMapper;
+import com.zxyj.mapper.UserMapper;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+import java.util.Date;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * 成长规划师-层级关系服务测试
+ * 覆盖场景:添加下级、查询下级/上级、递归查询、重复检查
+ */
+@SpringBootTest
+@Transactional
+public class GuideHierarchyServiceTest {
+
+    @Resource
+    private GuideHierarchyService hierarchyService;
+
+    @Resource
+    private UserMapper userMapper;
+
+    @Resource
+    private GuideHierarchyMapper hierarchyMapper;
+
+    @Resource
+    private JdbcTemplate jdbcTemplate;
+
+    @BeforeEach
+    public void ensureTableExists() {
+        jdbcTemplate.execute("DROP TABLE IF EXISTS `guide_hierarchy`");
+        jdbcTemplate.execute("CREATE TABLE `guide_hierarchy` (" +
+            "`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID'," +
+            "`parent_id` BIGINT NOT NULL COMMENT '上级成长规划师ID'," +
+            "`child_id` BIGINT NOT NULL COMMENT '下级成长规划师ID'," +
+            "`level` INT NOT NULL DEFAULT 1 COMMENT '层级深度'," +
+            "`status` VARCHAR(20) DEFAULT 'active' COMMENT '状态: active/inactive'," +
+            "`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间'," +
+            "`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'," +
+            "PRIMARY KEY (`id`)," +
+            "UNIQUE KEY `uk_parent_child` (`parent_id`, `child_id`)," +
+            "KEY `idx_child_id` (`child_id`)," +
+            "KEY `idx_level` (`level`)" +
+            ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='成长规划师层级关系表'");
+    }
+
+    private User createTestUser(Long id, String role, String nickname) {
+        User user = userMapper.selectById(id);
+        if (user == null) {
+            user = new User();
+            user.setId(id);
+            user.setOpenid("test_hierarchy_" + id);
+            user.setPhone("1380000" + String.format("%04d", id % 10000));
+            user.setFamilyId(0L);
+            user.setRole(role);
+            user.setNickname(nickname);
+            user.setCreatedAt(new Date());
+            user.setUpdatedAt(new Date());
+            userMapper.insert(user);
+        }
+        return user;
+    }
+
+    @Test
+    public void testAddChildGuide_Success() {
+        Long parentId = 81001L;
+        Long childId = 81002L;
+        createTestUser(parentId, "teacher", "上级指导师-81001");
+        createTestUser(childId, "teacher", "下级指导师-81002");
+
+        boolean result = hierarchyService.addChildGuide(parentId, childId);
+        assertTrue(result);
+
+        List<User> children = hierarchyService.getChildGuides(parentId);
+        assertTrue(children.stream().anyMatch(c -> c.getId().equals(childId)));
+    }
+
+    @Test
+    public void testAddChildGuide_Duplicate_ReturnsFalse() {
+        Long parentId = 81003L;
+        Long childId = 81004L;
+        createTestUser(parentId, "teacher", "上级指导师-81003");
+        createTestUser(childId, "teacher", "下级指导师-81004");
+
+        assertTrue(hierarchyService.addChildGuide(parentId, childId));
+        assertFalse(hierarchyService.addChildGuide(parentId, childId));
+    }
+
+    @Test
+    public void testGetChildGuides_DirectChildren() {
+        Long parentId = 81005L;
+        Long childId1 = 81006L;
+        Long childId2 = 81007L;
+        createTestUser(parentId, "teacher", "上级-81005");
+        createTestUser(childId1, "teacher", "下级-81006");
+        createTestUser(childId2, "teacher", "下级-81007");
+
+        hierarchyService.addChildGuide(parentId, childId1);
+        hierarchyService.addChildGuide(parentId, childId2);
+
+        List<User> children = hierarchyService.getChildGuides(parentId);
+        assertEquals(2, children.size());
+        assertTrue(children.stream().anyMatch(c -> c.getId().equals(childId1)));
+        assertTrue(children.stream().anyMatch(c -> c.getId().equals(childId2)));
+    }
+
+    @Test
+    public void testGetChildGuides_NoChildren() {
+        List<User> children = hierarchyService.getChildGuides(81999L);
+        assertNotNull(children);
+        assertTrue(children.isEmpty());
+    }
+
+    @Test
+    public void testGetAllChildGuides_Recursive() {
+        // 构建三级层级: 81008 -> 81009 -> 81010
+        Long topId = 81008L;
+        Long middleId = 81009L;
+        Long bottomId = 81010L;
+        createTestUser(topId, "teacher", "顶级-81008");
+        createTestUser(middleId, "teacher", "中级-81009");
+        createTestUser(bottomId, "teacher", "底层-81010");
+
+        hierarchyService.addChildGuide(topId, middleId);
+        hierarchyService.addChildGuide(middleId, bottomId);
+
+        List<User> allChildren = hierarchyService.getAllChildGuides(topId);
+        assertTrue(allChildren.stream().anyMatch(c -> c.getId().equals(middleId)));
+        assertTrue(allChildren.stream().anyMatch(c -> c.getId().equals(bottomId)));
+    }
+
+    @Test
+    public void testGetParentGuide() {
+        Long parentId = 81011L;
+        Long childId = 81012L;
+        createTestUser(parentId, "teacher", "上级-81011");
+        createTestUser(childId, "teacher", "下级-81012");
+
+        hierarchyService.addChildGuide(parentId, childId);
+
+        User parent = hierarchyService.getParentGuide(childId);
+        assertNotNull(parent);
+        assertEquals(parentId, parent.getId());
+    }
+
+    @Test
+    public void testGetParentGuide_NoParent() {
+        User parent = hierarchyService.getParentGuide(81998L);
+        assertNull(parent);
+    }
+
+    @Test
+    public void testIsChildGuide_DirectChild() {
+        Long parentId = 81013L;
+        Long childId = 81014L;
+        createTestUser(parentId, "teacher", "上级-81013");
+        createTestUser(childId, "teacher", "下级-81014");
+
+        hierarchyService.addChildGuide(parentId, childId);
+
+        assertTrue(hierarchyService.isChildGuide(parentId, childId));
+    }
+
+    @Test
+    public void testIsChildGuide_NestedChild() {
+        Long topId = 81015L;
+        Long middleId = 81016L;
+        Long bottomId = 81017L;
+        createTestUser(topId, "teacher", "顶级-81015");
+        createTestUser(middleId, "teacher", "中级-81016");
+        createTestUser(bottomId, "teacher", "底层-81017");
+
+        hierarchyService.addChildGuide(topId, middleId);
+        hierarchyService.addChildGuide(middleId, bottomId);
+
+        assertTrue(hierarchyService.isChildGuide(topId, bottomId));
+    }
+
+    @Test
+    public void testIsChildGuide_NotRelated() {
+        assertFalse(hierarchyService.isChildGuide(81997L, 81996L));
+    }
+}

+ 193 - 0
zxyj-backend/src/test/java/com/zxyj/service/GuidePackageServiceTest.java

@@ -0,0 +1,193 @@
+package com.zxyj.service;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.zxyj.entity.GuidePackage;
+import com.zxyj.entity.TaskTemplatePackage;
+import com.zxyj.mapper.GuidePackageMapper;
+import com.zxyj.mapper.TaskTemplatePackageMapper;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.util.*;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+@SpringBootTest
+public class GuidePackageServiceTest {
+
+    @Resource
+    private GuidePackageService guidePackageService;
+
+    @MockBean
+    private GuidePackageMapper guidePackageMapper;
+
+    @MockBean
+    private TaskTemplatePackageMapper taskTemplatePackageMapper;
+
+    private GuidePackage createGuidePackage(Long id, Long guideId, Long packageId, String status) {
+        GuidePackage gp = new GuidePackage();
+        gp.setId(id);
+        gp.setGuideId(guideId);
+        gp.setPackageId(packageId);
+        gp.setName("测试套餐");
+        gp.setPrice(new BigDecimal("199.00"));
+        gp.setCommissionRate(new BigDecimal("0.1"));
+        gp.setStatus(status);
+        gp.setCreatedAt(new Date());
+        gp.setUpdatedAt(new Date());
+        return gp;
+    }
+
+    private TaskTemplatePackage createTaskPackage(Long id) {
+        TaskTemplatePackage tp = new TaskTemplatePackage();
+        tp.setId(id);
+        tp.setName("模板套餐");
+        tp.setPrice(new BigDecimal("299.00"));
+        return tp;
+    }
+
+    @Test
+    public void addGuidePackage_Success() {
+        Long guideId = 1L;
+        Long packageId = 100L;
+
+        when(guidePackageMapper.selectCount(any(LambdaQueryWrapper.class))).thenReturn(0L);
+        when(taskTemplatePackageMapper.selectById(packageId)).thenReturn(createTaskPackage(packageId));
+        when(guidePackageMapper.insert(any(GuidePackage.class))).thenReturn(1);
+
+        boolean result = guidePackageService.addGuidePackage(guideId, packageId,
+            new BigDecimal("199.00"), new BigDecimal("0.1"));
+        assertTrue(result);
+    }
+
+    @Test
+    public void addGuidePackage_Duplicate_ReturnsFalse() {
+        when(guidePackageMapper.selectCount(any(LambdaQueryWrapper.class))).thenReturn(1L);
+
+        boolean result = guidePackageService.addGuidePackage(1L, 100L,
+            new BigDecimal("199.00"), new BigDecimal("0.1"));
+        assertFalse(result);
+    }
+
+    @Test
+    public void addGuidePackage_InvalidPackage_ReturnsFalse() {
+        when(guidePackageMapper.selectCount(any(LambdaQueryWrapper.class))).thenReturn(0L);
+        when(taskTemplatePackageMapper.selectById(999L)).thenReturn(null);
+
+        boolean result = guidePackageService.addGuidePackage(1L, 999L,
+            new BigDecimal("199.00"), new BigDecimal("0.1"));
+        assertFalse(result);
+    }
+
+    @Test
+    public void getGuidePackages_WithData() {
+        Long guideId = 1L;
+        List<GuidePackage> packages = Arrays.asList(
+            createGuidePackage(1L, guideId, 100L, "active"),
+            createGuidePackage(2L, guideId, 101L, "active")
+        );
+
+        when(guidePackageMapper.selectList(any(LambdaQueryWrapper.class))).thenReturn(packages);
+
+        List<GuidePackage> result = guidePackageService.getGuidePackages(guideId);
+        assertNotNull(result);
+        assertEquals(2, result.size());
+    }
+
+    @Test
+    public void getGuidePackages_NoData() {
+        when(guidePackageMapper.selectList(any(LambdaQueryWrapper.class))).thenReturn(new ArrayList<>());
+
+        List<GuidePackage> result = guidePackageService.getGuidePackages(1L);
+        assertNotNull(result);
+        assertTrue(result.isEmpty());
+    }
+
+    @Test
+    public void getGuidePackage_Found() {
+        GuidePackage gp = createGuidePackage(1L, 1L, 100L, "active");
+        when(guidePackageMapper.selectOne(any(LambdaQueryWrapper.class))).thenReturn(gp);
+
+        GuidePackage result = guidePackageService.getGuidePackage(1L, 100L);
+        assertNotNull(result);
+        assertEquals(1L, result.getGuideId());
+        assertEquals(100L, result.getPackageId());
+    }
+
+    @Test
+    public void getGuidePackage_NotFound() {
+        when(guidePackageMapper.selectOne(any(LambdaQueryWrapper.class))).thenReturn(null);
+
+        GuidePackage result = guidePackageService.getGuidePackage(1L, 999L);
+        assertNull(result);
+    }
+
+    @Test
+    public void updateGuidePackagePrice_Success() {
+        GuidePackage gp = createGuidePackage(1L, 1L, 100L, "active");
+        gp.setPrice(new BigDecimal("100.00"));
+
+        when(guidePackageMapper.selectOne(any(LambdaQueryWrapper.class))).thenReturn(gp);
+        when(guidePackageMapper.updateById(any(GuidePackage.class))).thenReturn(1);
+
+        boolean result = guidePackageService.updateGuidePackagePrice(1L, 100L, new BigDecimal("150.00"));
+        assertTrue(result);
+        assertEquals(new BigDecimal("150.00"), gp.getPrice());
+    }
+
+    @Test
+    public void updateGuidePackagePrice_NotFound_ReturnsFalse() {
+        when(guidePackageMapper.selectOne(any(LambdaQueryWrapper.class))).thenReturn(null);
+
+        boolean result = guidePackageService.updateGuidePackagePrice(1L, 999L, new BigDecimal("150.00"));
+        assertFalse(result);
+    }
+
+    @Test
+    public void deleteGuidePackage_Success() {
+        GuidePackage gp = createGuidePackage(1L, 1L, 100L, "active");
+        when(guidePackageMapper.selectOne(any(LambdaQueryWrapper.class))).thenReturn(gp);
+        when(guidePackageMapper.updateById(any(GuidePackage.class))).thenReturn(1);
+
+        boolean result = guidePackageService.deleteGuidePackage(1L, 100L);
+        assertTrue(result);
+        assertEquals("inactive", gp.getStatus());
+    }
+
+    @Test
+    public void deleteGuidePackage_NotFound_ReturnsFalse() {
+        when(guidePackageMapper.selectOne(any(LambdaQueryWrapper.class))).thenReturn(null);
+
+        boolean result = guidePackageService.deleteGuidePackage(1L, 999L);
+        assertFalse(result);
+    }
+
+    @Test
+    public void getActivePackages_ReturnsAllActive() {
+        List<GuidePackage> packages = Arrays.asList(
+            createGuidePackage(1L, 1L, 100L, "active"),
+            createGuidePackage(2L, 2L, 101L, "active")
+        );
+        when(guidePackageMapper.selectList(any(LambdaQueryWrapper.class))).thenReturn(packages);
+
+        List<GuidePackage> result = guidePackageService.getActivePackages();
+        assertEquals(2, result.size());
+    }
+
+    @Test
+    public void getPackagesByLevel_ReturnsFiltered() {
+        List<GuidePackage> packages = Collections.singletonList(
+            createGuidePackage(1L, 1L, 100L, "active")
+        );
+        packages.get(0).setLevel("senior");
+        when(guidePackageMapper.selectList(any(LambdaQueryWrapper.class))).thenReturn(packages);
+
+        List<GuidePackage> result = guidePackageService.getPackagesByLevel("senior");
+        assertEquals(1, result.size());
+    }
+}