From 0f60af4728662e076ab04a2d352eed6286f294be Mon Sep 17 00:00:00 2001
From: dongyukun <1208714201@qq.com>
Date: 星期一, 16 十二月 2024 09:28:43 +0800
Subject: [PATCH] 用户名翻译

---
 /dev/null                                                                                                                      |  765 ----------------------------------------------------------
 iailab-module-system/iailab-module-system-api/src/main/java/com/iailab/module/system/api/user/AdminUserApi.java                |    4 
 iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/auth/AuthController.java |    2 
 3 files changed, 4 insertions(+), 767 deletions(-)

diff --git a/iailab-module-system/iailab-module-system-api/src/main/java/com/iailab/module/system/api/user/AdminUserApi.java b/iailab-module-system/iailab-module-system-api/src/main/java/com/iailab/module/system/api/user/AdminUserApi.java
index 9f81b60..42710d2 100644
--- a/iailab-module-system/iailab-module-system-api/src/main/java/com/iailab/module/system/api/user/AdminUserApi.java
+++ b/iailab-module-system/iailab-module-system-api/src/main/java/com/iailab/module/system/api/user/AdminUserApi.java
@@ -1,6 +1,7 @@
 package com.iailab.module.system.api.user;
 
 import cn.hutool.core.convert.Convert;
+import com.fhs.core.trans.anno.AutoTrans;
 import com.iailab.framework.common.pojo.CommonResult;
 import com.iailab.framework.common.util.collection.CollectionUtils;
 import com.iailab.module.system.api.user.dto.AdminUserRespDTO;
@@ -14,12 +15,13 @@
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestParam;
+import static com.iailab.module.system.api.user.AdminUserApi.PREFIX;
 
 import java.util.*;
 
 @FeignClient(name = ApiConstants.NAME)
 @Tag(name = "RPC 服务 - 管理员用户")
-//@AutoTrans(namespace = PREFIX, fields = {"nickname"}) // TODO @iailab:需要 easy-trans 做个 bugfix
+@AutoTrans(namespace = PREFIX, fields = {"nickname"}) // TODO @iailab:需要 easy-trans 做个 bugfix
 public interface AdminUserApi extends AutoTransable<AdminUserRespDTO> {
 
     String PREFIX = ApiConstants.PREFIX + "/user";
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/auth/AuthController.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/auth/AuthController.java
index d64c0ca..2de4f9c 100644
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/auth/AuthController.java
+++ b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/auth/AuthController.java
@@ -136,7 +136,7 @@
         Set<Long> menuIds = permissionService.getRoleMenuListByRoleId(convertSet(roles, RoleDO::getId));
         List<MenuDO> menuList = menuService.getMenuList(menuIds);
         menuList = menuService.filterDisableMenus(menuList);
-        menuList = menuService.filterMenus(menuList, "system");
+//        menuList = menuService.filterMenus(menuList, "system");
 
         // 2. 拼接结果返回
         return success(AuthConvert.INSTANCE.convert(user, roles, menuList));
diff --git a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/framework/sms/core/client/impl/AliyunSmsClientTest.java b/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/framework/sms/core/client/impl/AliyunSmsClientTest.java
deleted file mode 100644
index f65b976..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/framework/sms/core/client/impl/AliyunSmsClientTest.java
+++ /dev/null
@@ -1,188 +0,0 @@
-package com.iailab.module.system.framework.sms.core.client.impl;
-
-import cn.hutool.core.util.ReflectUtil;
-import com.iailab.framework.common.core.KeyValue;
-import com.iailab.framework.common.util.collection.MapUtils;
-import com.iailab.framework.test.core.ut.BaseMockitoUnitTest;
-import com.iailab.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO;
-import com.iailab.module.system.framework.sms.core.client.dto.SmsSendRespDTO;
-import com.iailab.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO;
-import com.iailab.module.system.framework.sms.core.client.impl.AliyunSmsClient;
-import com.iailab.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
-import com.iailab.module.system.framework.sms.core.property.SmsChannelProperties;
-import com.aliyuncs.IAcsClient;
-import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateRequest;
-import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateResponse;
-import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
-import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
-import com.google.common.collect.Lists;
-import org.junit.jupiter.api.Test;
-import org.mockito.ArgumentMatcher;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-
-import java.time.LocalDateTime;
-import java.util.List;
-
-import static com.iailab.framework.common.util.json.JsonUtils.toJsonString;
-import static com.iailab.framework.test.core.util.RandomUtils.*;
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.argThat;
-import static org.mockito.Mockito.when;
-
-/**
- * {@link AliyunSmsClient} 的单元测试
- *
- * @author iailab
- */
-public class AliyunSmsClientTest extends BaseMockitoUnitTest {
-
-    private final SmsChannelProperties properties = new SmsChannelProperties()
-            .setApiKey(randomString()) // 随机一个 apiKey,避免构建报错
-            .setApiSecret(randomString()) // 随机一个 apiSecret,避免构建报错
-            .setSignature("iailab");
-
-    @InjectMocks
-    private final AliyunSmsClient smsClient = new AliyunSmsClient(properties);
-
-    @Mock
-    private IAcsClient client;
-
-    @Test
-    public void testDoInit() {
-        // 准备参数
-        // mock 方法
-
-        // 调用
-        smsClient.doInit();
-        // 断言
-        assertNotSame(client, ReflectUtil.getFieldValue(smsClient, "acsClient"));
-    }
-
-    @Test
-    public void tesSendSms_success() throws Throwable {
-        // 准备参数
-        Long sendLogId = randomLongId();
-        String mobile = randomString();
-        String apiTemplateId = randomString();
-        List<KeyValue<String, Object>> templateParams = Lists.newArrayList(
-                new KeyValue<>("code", 1234), new KeyValue<>("op", "login"));
-        // mock 方法
-        SendSmsResponse response = randomPojo(SendSmsResponse.class, o -> o.setCode("OK"));
-        when(client.getAcsResponse(argThat((ArgumentMatcher<SendSmsRequest>) acsRequest -> {
-            assertEquals(mobile, acsRequest.getPhoneNumbers());
-            assertEquals(properties.getSignature(), acsRequest.getSignName());
-            assertEquals(apiTemplateId, acsRequest.getTemplateCode());
-            assertEquals(toJsonString(MapUtils.convertMap(templateParams)), acsRequest.getTemplateParam());
-            assertEquals(sendLogId.toString(), acsRequest.getOutId());
-            return true;
-        }))).thenReturn(response);
-
-        // 调用
-        SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile,
-                apiTemplateId, templateParams);
-        // 断言
-        assertTrue(result.getSuccess());
-        assertEquals(response.getRequestId(), result.getApiRequestId());
-        assertEquals(response.getCode(), result.getApiCode());
-        assertEquals(response.getMessage(), result.getApiMsg());
-        assertEquals(response.getBizId(), result.getSerialNo());
-    }
-
-    @Test
-    public void tesSendSms_fail() throws Throwable {
-        // 准备参数
-        Long sendLogId = randomLongId();
-        String mobile = randomString();
-        String apiTemplateId = randomString();
-        List<KeyValue<String, Object>> templateParams = Lists.newArrayList(
-                new KeyValue<>("code", 1234), new KeyValue<>("op", "login"));
-        // mock 方法
-        SendSmsResponse response = randomPojo(SendSmsResponse.class, o -> o.setCode("ERROR"));
-        when(client.getAcsResponse(argThat((ArgumentMatcher<SendSmsRequest>) acsRequest -> {
-            assertEquals(mobile, acsRequest.getPhoneNumbers());
-            assertEquals(properties.getSignature(), acsRequest.getSignName());
-            assertEquals(apiTemplateId, acsRequest.getTemplateCode());
-            assertEquals(toJsonString(MapUtils.convertMap(templateParams)), acsRequest.getTemplateParam());
-            assertEquals(sendLogId.toString(), acsRequest.getOutId());
-            return true;
-        }))).thenReturn(response);
-
-        // 调用
-        SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile, apiTemplateId, templateParams);
-        // 断言
-        assertFalse(result.getSuccess());
-        assertEquals(response.getRequestId(), result.getApiRequestId());
-        assertEquals(response.getCode(), result.getApiCode());
-        assertEquals(response.getMessage(), result.getApiMsg());
-        assertEquals(response.getBizId(), result.getSerialNo());
-    }
-
-    @Test
-    public void testParseSmsReceiveStatus() {
-        // 准备参数
-        String text = "[\n" +
-                "  {\n" +
-                "    \"phone_number\" : \"13900000001\",\n" +
-                "    \"send_time\" : \"2017-01-01 11:12:13\",\n" +
-                "    \"report_time\" : \"2017-02-02 22:23:24\",\n" +
-                "    \"success\" : true,\n" +
-                "    \"err_code\" : \"DELIVERED\",\n" +
-                "    \"err_msg\" : \"用户接收成功\",\n" +
-                "    \"sms_size\" : \"1\",\n" +
-                "    \"biz_id\" : \"12345\",\n" +
-                "    \"out_id\" : \"67890\"\n" +
-                "  }\n" +
-                "]";
-        // mock 方法
-
-        // 调用
-        List<SmsReceiveRespDTO> statuses = smsClient.parseSmsReceiveStatus(text);
-        // 断言
-        assertEquals(1, statuses.size());
-        assertTrue(statuses.get(0).getSuccess());
-        assertEquals("DELIVERED", statuses.get(0).getErrorCode());
-        assertEquals("用户接收成功", statuses.get(0).getErrorMsg());
-        assertEquals("13900000001", statuses.get(0).getMobile());
-        assertEquals(LocalDateTime.of(2017, 2, 2, 22, 23, 24),
-                statuses.get(0).getReceiveTime());
-        assertEquals("12345", statuses.get(0).getSerialNo());
-        assertEquals(67890L, statuses.get(0).getLogId());
-    }
-
-    @Test
-    public void testGetSmsTemplate() throws Throwable {
-        // 准备参数
-        String apiTemplateId = randomString();
-        // mock 方法
-        QuerySmsTemplateResponse response = randomPojo(QuerySmsTemplateResponse.class, o -> {
-            o.setCode("OK");
-            o.setTemplateStatus(1); // 设置模板通过
-        });
-        when(client.getAcsResponse(argThat((ArgumentMatcher<QuerySmsTemplateRequest>) acsRequest -> {
-            assertEquals(apiTemplateId, acsRequest.getTemplateCode());
-            return true;
-        }))).thenReturn(response);
-
-        // 调用
-        SmsTemplateRespDTO result = smsClient.getSmsTemplate(apiTemplateId);
-        // 断言
-        assertEquals(response.getTemplateCode(), result.getId());
-        assertEquals(response.getTemplateContent(), result.getContent());
-        assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), result.getAuditStatus());
-        assertEquals(response.getReason(), result.getAuditReason());
-    }
-
-    @Test
-    public void testConvertSmsTemplateAuditStatus() {
-        assertEquals(SmsTemplateAuditStatusEnum.CHECKING.getStatus(),
-                smsClient.convertSmsTemplateAuditStatus(0));
-        assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(),
-                smsClient.convertSmsTemplateAuditStatus(1));
-        assertEquals(SmsTemplateAuditStatusEnum.FAIL.getStatus(),
-                smsClient.convertSmsTemplateAuditStatus(2));
-        assertThrows(IllegalArgumentException.class, () -> smsClient.convertSmsTemplateAuditStatus(3),
-                "未知审核状态(3)");
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/framework/sms/core/client/impl/TencentSmsClientTest.java b/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/framework/sms/core/client/impl/TencentSmsClientTest.java
deleted file mode 100644
index 541b9bc..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/framework/sms/core/client/impl/TencentSmsClientTest.java
+++ /dev/null
@@ -1,230 +0,0 @@
-package com.iailab.module.system.framework.sms.core.client.impl;
-
-import cn.hutool.core.util.ReflectUtil;
-import com.iailab.framework.common.core.KeyValue;
-import com.iailab.framework.common.util.collection.ArrayUtils;
-import com.iailab.framework.common.util.collection.MapUtils;
-import com.iailab.framework.common.util.json.JsonUtils;
-import com.iailab.framework.test.core.ut.BaseMockitoUnitTest;
-import com.iailab.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO;
-import com.iailab.module.system.framework.sms.core.client.dto.SmsSendRespDTO;
-import com.iailab.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO;
-import com.iailab.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
-import com.iailab.module.system.framework.sms.core.property.SmsChannelProperties;
-import com.google.common.collect.Lists;
-import com.tencentcloudapi.sms.v20210111.SmsClient;
-import com.tencentcloudapi.sms.v20210111.models.DescribeSmsTemplateListResponse;
-import com.tencentcloudapi.sms.v20210111.models.DescribeTemplateListStatus;
-import com.tencentcloudapi.sms.v20210111.models.SendSmsResponse;
-import com.tencentcloudapi.sms.v20210111.models.SendStatus;
-import org.junit.jupiter.api.Test;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-
-import java.time.LocalDateTime;
-import java.util.ArrayList;
-import java.util.List;
-
-import static com.iailab.framework.common.util.json.JsonUtils.toJsonString;
-import static com.iailab.framework.test.core.util.RandomUtils.*;
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.argThat;
-import static org.mockito.Mockito.when;
-
-/**
- * {@link TencentSmsClient} 的单元测试
- *
- * @author shiwp
- */
-public class TencentSmsClientTest extends BaseMockitoUnitTest {
-
-    private final SmsChannelProperties properties = new SmsChannelProperties()
-            .setApiKey(randomString() + " " + randomString()) // 随机一个 apiKey,避免构建报错
-            .setApiSecret(randomString()) // 随机一个 apiSecret,避免构建报错
-            .setSignature("iailab");
-
-    @InjectMocks
-    private TencentSmsClient smsClient = new TencentSmsClient(properties);
-
-    @Mock
-    private SmsClient client;
-
-    @Test
-    public void testDoInit() {
-        // 准备参数
-        // mock 方法
-
-        // 调用
-        smsClient.doInit();
-        // 断言
-        assertNotSame(client, ReflectUtil.getFieldValue(smsClient, "client"));
-    }
-
-    @Test
-    public void testRefresh() {
-        // 准备参数
-        SmsChannelProperties p = new SmsChannelProperties()
-                .setApiKey(randomString() + " " + randomString()) // 随机一个 apiKey,避免构建报错
-                .setApiSecret(randomString()) // 随机一个 apiSecret,避免构建报错
-                .setSignature("iailab");
-        // 调用
-        smsClient.refresh(p);
-        // 断言
-        assertNotSame(client, ReflectUtil.getFieldValue(smsClient, "client"));
-    }
-
-    @Test
-    public void testDoSendSms_success() throws Throwable {
-        // 准备参数
-        Long sendLogId = randomLongId();
-        String mobile = randomString();
-        String apiTemplateId = randomString();
-        List<KeyValue<String, Object>> templateParams = Lists.newArrayList(
-                new KeyValue<>("1", 1234), new KeyValue<>("2", "login"));
-        String requestId = randomString();
-        String serialNo = randomString();
-        // mock 方法
-        SendSmsResponse response = randomPojo(SendSmsResponse.class, o -> {
-            o.setRequestId(requestId);
-            SendStatus[] sendStatuses = new SendStatus[1];
-            o.setSendStatusSet(sendStatuses);
-            SendStatus sendStatus = new SendStatus();
-            sendStatuses[0] = sendStatus;
-            sendStatus.setCode(TencentSmsClient.API_CODE_SUCCESS);
-            sendStatus.setMessage("send success");
-            sendStatus.setSerialNo(serialNo);
-        });
-        when(client.SendSms(argThat(request -> {
-            assertEquals(mobile, request.getPhoneNumberSet()[0]);
-            assertEquals(properties.getSignature(), request.getSignName());
-            assertEquals(apiTemplateId, request.getTemplateId());
-            assertEquals(toJsonString(ArrayUtils.toArray(new ArrayList<>(MapUtils.convertMap(templateParams).values()), String::valueOf)),
-                    toJsonString(request.getTemplateParamSet()));
-            assertEquals(sendLogId, ReflectUtil.getFieldValue(JsonUtils.parseObject(request.getSessionContext(), TencentSmsClient.SessionContext.class), "logId"));
-            return true;
-        }))).thenReturn(response);
-
-        // 调用
-        SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile, apiTemplateId, templateParams);
-        // 断言
-        assertTrue(result.getSuccess());
-        assertEquals(response.getRequestId(), result.getApiRequestId());
-        assertEquals(response.getSendStatusSet()[0].getCode(), result.getApiCode());
-        assertEquals(response.getSendStatusSet()[0].getMessage(), result.getApiMsg());
-        assertEquals(response.getSendStatusSet()[0].getSerialNo(), result.getSerialNo());
-    }
-
-    @Test
-    public void testDoSendSms_fail() throws Throwable {
-        // 准备参数
-        Long sendLogId = randomLongId();
-        String mobile = randomString();
-        String apiTemplateId = randomString();
-        List<KeyValue<String, Object>> templateParams = Lists.newArrayList(
-                new KeyValue<>("1", 1234), new KeyValue<>("2", "login"));
-        String requestId = randomString();
-        String serialNo = randomString();
-        // mock 方法
-        SendSmsResponse response = randomPojo(SendSmsResponse.class, o -> {
-            o.setRequestId(requestId);
-            SendStatus[] sendStatuses = new SendStatus[1];
-            o.setSendStatusSet(sendStatuses);
-            SendStatus sendStatus = new SendStatus();
-            sendStatuses[0] = sendStatus;
-            sendStatus.setCode("ERROR");
-            sendStatus.setMessage("send success");
-            sendStatus.setSerialNo(serialNo);
-        });
-        when(client.SendSms(argThat(request -> {
-            assertEquals(mobile, request.getPhoneNumberSet()[0]);
-            assertEquals(properties.getSignature(), request.getSignName());
-            assertEquals(apiTemplateId, request.getTemplateId());
-            assertEquals(toJsonString(ArrayUtils.toArray(new ArrayList<>(MapUtils.convertMap(templateParams).values()), String::valueOf)),
-                    toJsonString(request.getTemplateParamSet()));
-            assertEquals(sendLogId, ReflectUtil.getFieldValue(JsonUtils.parseObject(request.getSessionContext(), TencentSmsClient.SessionContext.class), "logId"));
-            return true;
-        }))).thenReturn(response);
-
-        // 调用
-        SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile, apiTemplateId, templateParams);
-        // 断言
-        assertFalse(result.getSuccess());
-        assertEquals(response.getRequestId(), result.getApiRequestId());
-        assertEquals(response.getSendStatusSet()[0].getCode(), result.getApiCode());
-        assertEquals(response.getSendStatusSet()[0].getMessage(), result.getApiMsg());
-        assertEquals(response.getSendStatusSet()[0].getSerialNo(), result.getSerialNo());
-    }
-
-    @Test
-    public void testParseSmsReceiveStatus() {
-        // 准备参数
-        String text = "[\n" +
-                "    {\n" +
-                "        \"user_receive_time\": \"2015-10-17 08:03:04\",\n" +
-                "        \"nationcode\": \"86\",\n" +
-                "        \"mobile\": \"13900000001\",\n" +
-                "        \"report_status\": \"SUCCESS\",\n" +
-                "        \"errmsg\": \"DELIVRD\",\n" +
-                "        \"description\": \"用户短信送达成功\",\n" +
-                "        \"sid\": \"12345\",\n" +
-                "        \"ext\": {\"logId\":\"67890\"}\n" +
-                "    }\n" +
-                "]";
-        // mock 方法
-
-        // 调用
-        List<SmsReceiveRespDTO> statuses = smsClient.parseSmsReceiveStatus(text);
-        // 断言
-        assertEquals(1, statuses.size());
-        assertTrue(statuses.get(0).getSuccess());
-        assertEquals("DELIVRD", statuses.get(0).getErrorCode());
-        assertEquals("用户短信送达成功", statuses.get(0).getErrorMsg());
-        assertEquals("13900000001", statuses.get(0).getMobile());
-        assertEquals(LocalDateTime.of(2015, 10, 17, 8, 3, 4), statuses.get(0).getReceiveTime());
-        assertEquals("12345", statuses.get(0).getSerialNo());
-        assertEquals(67890L, statuses.get(0).getLogId());
-    }
-
-    @Test
-    public void testGetSmsTemplate() throws Throwable {
-        // 准备参数
-        Long apiTemplateId = randomLongId();
-        String requestId = randomString();
-
-        // mock 方法
-        DescribeSmsTemplateListResponse response = randomPojo(DescribeSmsTemplateListResponse.class, o -> {
-            DescribeTemplateListStatus[] describeTemplateListStatuses = new DescribeTemplateListStatus[1];
-            DescribeTemplateListStatus templateStatus = new DescribeTemplateListStatus();
-            templateStatus.setTemplateId(apiTemplateId);
-            templateStatus.setStatusCode(0L);// 设置模板通过
-            describeTemplateListStatuses[0] = templateStatus;
-            o.setDescribeTemplateStatusSet(describeTemplateListStatuses);
-            o.setRequestId(requestId);
-        });
-        when(client.DescribeSmsTemplateList(argThat(request -> {
-            assertEquals(apiTemplateId, request.getTemplateIdSet()[0]);
-            return true;
-        }))).thenReturn(response);
-
-        // 调用
-        SmsTemplateRespDTO result = smsClient.getSmsTemplate(apiTemplateId.toString());
-        // 断言
-        assertEquals(response.getDescribeTemplateStatusSet()[0].getTemplateId().toString(), result.getId());
-        assertEquals(response.getDescribeTemplateStatusSet()[0].getTemplateContent(), result.getContent());
-        assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), result.getAuditStatus());
-        assertEquals(response.getDescribeTemplateStatusSet()[0].getReviewReply(), result.getAuditReason());
-    }
-
-    @Test
-    public void testConvertSmsTemplateAuditStatus() {
-        assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(),
-                smsClient.convertSmsTemplateAuditStatus(0));
-        assertEquals(SmsTemplateAuditStatusEnum.CHECKING.getStatus(),
-                smsClient.convertSmsTemplateAuditStatus(1));
-        assertEquals(SmsTemplateAuditStatusEnum.FAIL.getStatus(),
-                smsClient.convertSmsTemplateAuditStatus(-1));
-        assertThrows(IllegalArgumentException.class, () -> smsClient.convertSmsTemplateAuditStatus(3),
-                "未知审核状态(3)");
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/auth/AdminAuthServiceImplTest.java b/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/auth/AdminAuthServiceImplTest.java
deleted file mode 100644
index 40c0857..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/auth/AdminAuthServiceImplTest.java
+++ /dev/null
@@ -1,381 +0,0 @@
-package com.iailab.module.system.service.auth;
-
-import cn.hutool.core.util.ReflectUtil;
-import com.iailab.framework.common.enums.CommonStatusEnum;
-import com.iailab.framework.common.enums.UserTypeEnum;
-import com.iailab.framework.common.pojo.CommonResult;
-import com.iailab.framework.test.core.ut.BaseDbUnitTest;
-import com.iailab.module.system.api.sms.SmsCodeApi;
-import com.iailab.module.system.api.social.dto.SocialUserBindReqDTO;
-import com.iailab.module.system.api.social.dto.SocialUserRespDTO;
-import com.iailab.module.system.controller.admin.auth.vo.*;
-import com.iailab.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
-import com.iailab.module.system.dal.dataobject.user.AdminUserDO;
-import com.iailab.module.system.enums.logger.LoginLogTypeEnum;
-import com.iailab.module.system.enums.logger.LoginResultEnum;
-import com.iailab.module.system.enums.sms.SmsSceneEnum;
-import com.iailab.module.system.enums.social.SocialTypeEnum;
-import com.iailab.module.system.service.logger.LoginLogService;
-import com.iailab.module.system.service.member.MemberService;
-import com.iailab.module.system.service.oauth2.OAuth2TokenService;
-import com.iailab.module.system.service.social.SocialUserService;
-import com.iailab.module.system.service.user.AdminUserService;
-import com.xingyuv.captcha.model.common.ResponseModel;
-import com.xingyuv.captcha.service.CaptchaService;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.context.annotation.Import;
-
-import javax.annotation.Resource;
-import javax.validation.ConstraintViolationException;
-import javax.validation.Validation;
-import javax.validation.Validator;
-
-import static cn.hutool.core.util.RandomUtil.randomEle;
-import static com.iailab.framework.common.pojo.CommonResult.success;
-import static com.iailab.framework.test.core.util.AssertUtils.assertPojoEquals;
-import static com.iailab.framework.test.core.util.AssertUtils.assertServiceException;
-import static com.iailab.framework.test.core.util.RandomUtils.randomPojo;
-import static com.iailab.framework.test.core.util.RandomUtils.randomString;
-import static com.iailab.module.system.enums.ErrorCodeConstants.*;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.*;
-
-@Import(AdminAuthServiceImpl.class)
-public class AdminAuthServiceImplTest extends BaseDbUnitTest {
-
-    @Resource
-    private AdminAuthServiceImpl authService;
-
-    @MockBean
-    private AdminUserService userService;
-    @MockBean
-    private CaptchaService captchaService;
-    @MockBean
-    private LoginLogService loginLogService;
-    @MockBean
-    private SocialUserService socialUserService;
-    @MockBean
-    private SmsCodeApi smsCodeApi;
-    @MockBean
-    private OAuth2TokenService oauth2TokenService;
-    @MockBean
-    private MemberService memberService;
-    @MockBean
-    private Validator validator;
-
-    @BeforeEach
-    public void setUp() {
-        ReflectUtil.setFieldValue(authService, "captchaEnable", true);
-        // 注入一个 Validator 对象
-        ReflectUtil.setFieldValue(authService, "validator",
-                Validation.buildDefaultValidatorFactory().getValidator());
-    }
-
-    @Test
-    public void testAuthenticate_success() {
-        // 准备参数
-        String username = randomString();
-        String password = randomString();
-        // mock user 数据
-        AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setUsername(username)
-                .setPassword(password).setStatus(CommonStatusEnum.ENABLE.getStatus()));
-        when(userService.getUserByUsername(eq(username))).thenReturn(user);
-        // mock password 匹配
-        when(userService.isPasswordMatch(eq(password), eq(user.getPassword()))).thenReturn(true);
-
-        // 调用
-        AdminUserDO loginUser = authService.authenticate(username, password);
-        // 校验
-        assertPojoEquals(user, loginUser);
-    }
-
-    @Test
-    public void testAuthenticate_userNotFound() {
-        // 准备参数
-        String username = randomString();
-        String password = randomString();
-
-        // 调用, 并断言异常
-        assertServiceException(() -> authService.authenticate(username, password),
-                AUTH_LOGIN_BAD_CREDENTIALS);
-        verify(loginLogService).createLoginLog(
-                argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType())
-                        && o.getResult().equals(LoginResultEnum.BAD_CREDENTIALS.getResult())
-                        && o.getUserId() == null)
-        );
-    }
-
-    @Test
-    public void testAuthenticate_badCredentials() {
-        // 准备参数
-        String username = randomString();
-        String password = randomString();
-        // mock user 数据
-        AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setUsername(username)
-                .setPassword(password).setStatus(CommonStatusEnum.ENABLE.getStatus()));
-        when(userService.getUserByUsername(eq(username))).thenReturn(user);
-
-        // 调用, 并断言异常
-        assertServiceException(() -> authService.authenticate(username, password),
-                AUTH_LOGIN_BAD_CREDENTIALS);
-        verify(loginLogService).createLoginLog(
-                argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType())
-                        && o.getResult().equals(LoginResultEnum.BAD_CREDENTIALS.getResult())
-                        && o.getUserId().equals(user.getId()))
-        );
-    }
-
-    @Test
-    public void testAuthenticate_userDisabled() {
-        // 准备参数
-        String username = randomString();
-        String password = randomString();
-        // mock user 数据
-        AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setUsername(username)
-                .setPassword(password).setStatus(CommonStatusEnum.DISABLE.getStatus()));
-        when(userService.getUserByUsername(eq(username))).thenReturn(user);
-        // mock password 匹配
-        when(userService.isPasswordMatch(eq(password), eq(user.getPassword()))).thenReturn(true);
-
-        // 调用, 并断言异常
-        assertServiceException(() -> authService.authenticate(username, password),
-                AUTH_LOGIN_USER_DISABLED);
-        verify(loginLogService).createLoginLog(
-                argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType())
-                        && o.getResult().equals(LoginResultEnum.USER_DISABLED.getResult())
-                        && o.getUserId().equals(user.getId()))
-        );
-    }
-
-    @Test
-    public void testLogin_success() {
-        // 准备参数
-        AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class, o ->
-                o.setUsername("test_username").setPassword("test_password")
-                        .setSocialType(randomEle(SocialTypeEnum.values()).getType()));
-
-        // mock 验证码正确
-        ReflectUtil.setFieldValue(authService, "captchaEnable", false);
-        // mock user 数据
-        AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setId(1L).setUsername("test_username")
-                .setPassword("test_password").setStatus(CommonStatusEnum.ENABLE.getStatus()));
-        when(userService.getUserByUsername(eq("test_username"))).thenReturn(user);
-        // mock password 匹配
-        when(userService.isPasswordMatch(eq("test_password"), eq(user.getPassword()))).thenReturn(true);
-        // mock 缓存登录用户到 Redis
-        OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class, o -> o.setUserId(1L)
-                .setUserType(UserTypeEnum.ADMIN.getValue()));
-        when(oauth2TokenService.createAccessToken(eq(1L), eq(UserTypeEnum.ADMIN.getValue()), eq("default"), isNull()))
-                .thenReturn(accessTokenDO);
-
-        // 调用,并校验
-        AuthLoginRespVO loginRespVO = authService.login(reqVO);
-        assertPojoEquals(accessTokenDO, loginRespVO);
-        // 校验调用参数
-        verify(loginLogService).createLoginLog(
-                argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType())
-                        && o.getResult().equals(LoginResultEnum.SUCCESS.getResult())
-                        && o.getUserId().equals(user.getId()))
-        );
-        verify(socialUserService).bindSocialUser(eq(new SocialUserBindReqDTO(
-                user.getId(), UserTypeEnum.ADMIN.getValue(),
-                reqVO.getSocialType(), reqVO.getSocialCode(), reqVO.getSocialState())));
-    }
-
-    @Test
-    public void testSendSmsCode() {
-        // 准备参数
-        String mobile = randomString();
-        Integer scene = randomEle(SmsSceneEnum.values()).getScene();
-        AuthSmsSendReqVO reqVO = new AuthSmsSendReqVO(mobile, scene);
-        // mock 方法(用户信息)
-        AdminUserDO user = randomPojo(AdminUserDO.class);
-        when(userService.getUserByMobile(eq(mobile))).thenReturn(user);
-
-        // 调用
-        authService.sendSmsCode(reqVO);
-        // 断言
-        verify(smsCodeApi).sendSmsCode(argThat(sendReqDTO -> {
-            assertEquals(mobile, sendReqDTO.getMobile());
-            assertEquals(scene, sendReqDTO.getScene());
-            return true;
-        }));
-    }
-
-    @Test
-    public void testSmsLogin_success() {
-        // 准备参数
-        String mobile = randomString();
-        String code = randomString();
-        AuthSmsLoginReqVO reqVO = new AuthSmsLoginReqVO(mobile, code);
-        // mock 方法(校验验证码)
-        when(smsCodeApi.useSmsCode(argThat(reqDTO -> {
-            assertEquals(mobile, reqDTO.getMobile());
-            assertEquals(code, reqDTO.getCode());
-            assertEquals(SmsSceneEnum.ADMIN_MEMBER_LOGIN.getScene(), reqDTO.getScene());
-            return true;
-        }))).thenReturn(success(true));
-        // mock 方法(用户信息)
-        AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setId(1L));
-        when(userService.getUserByMobile(eq(mobile))).thenReturn(user);
-        // mock 缓存登录用户到 Redis
-        OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class, o -> o.setUserId(1L)
-                .setUserType(UserTypeEnum.ADMIN.getValue()));
-        when(oauth2TokenService.createAccessToken(eq(1L), eq(UserTypeEnum.ADMIN.getValue()), eq("default"), isNull()))
-                .thenReturn(accessTokenDO);
-
-        // 调用,并断言
-        AuthLoginRespVO loginRespVO = authService.smsLogin(reqVO);
-        assertPojoEquals(accessTokenDO, loginRespVO);
-        // 断言调用
-        verify(loginLogService).createLoginLog(
-                argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_MOBILE.getType())
-                        && o.getResult().equals(LoginResultEnum.SUCCESS.getResult())
-                        && o.getUserId().equals(user.getId()))
-        );
-    }
-
-    @Test
-    public void testSocialLogin_success() {
-        // 准备参数
-        AuthSocialLoginReqVO reqVO = randomPojo(AuthSocialLoginReqVO.class);
-        // mock 方法(绑定的用户编号)
-        Long userId = 1L;
-        when(socialUserService.getSocialUserByCode(eq(UserTypeEnum.ADMIN.getValue()), eq(reqVO.getType()),
-                eq(reqVO.getCode()), eq(reqVO.getState()))).thenReturn(new SocialUserRespDTO(randomString(), randomString(), randomString(), userId));
-        // mock(用户)
-        AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setId(userId));
-        when(userService.getUser(eq(userId))).thenReturn(user);
-        // mock 缓存登录用户到 Redis
-        OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class, o -> o.setUserId(1L)
-                .setUserType(UserTypeEnum.ADMIN.getValue()));
-        when(oauth2TokenService.createAccessToken(eq(1L), eq(UserTypeEnum.ADMIN.getValue()), eq("default"), isNull()))
-                .thenReturn(accessTokenDO);
-
-        // 调用,并断言
-        AuthLoginRespVO loginRespVO = authService.socialLogin(reqVO);
-        assertPojoEquals(accessTokenDO, loginRespVO);
-        // 断言调用
-        verify(loginLogService).createLoginLog(
-                argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_SOCIAL.getType())
-                        && o.getResult().equals(LoginResultEnum.SUCCESS.getResult())
-                        && o.getUserId().equals(user.getId()))
-        );
-    }
-
-    @Test
-    public void testValidateCaptcha_successWithEnable() {
-        // 准备参数
-        AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class);
-
-        // mock 验证码打开
-        ReflectUtil.setFieldValue(authService, "captchaEnable", true);
-        // mock 验证通过
-        when(captchaService.verification(argThat(captchaVO -> {
-            assertEquals(reqVO.getCaptchaVerification(), captchaVO.getCaptchaVerification());
-            return true;
-        }))).thenReturn(ResponseModel.success());
-
-        // 调用,无需断言
-        authService.validateCaptcha(reqVO);
-    }
-
-    @Test
-    public void testValidateCaptcha_successWithDisable() {
-        // 准备参数
-        AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class);
-
-        // mock 验证码关闭
-        ReflectUtil.setFieldValue(authService, "captchaEnable", false);
-
-        // 调用,无需断言
-        authService.validateCaptcha(reqVO);
-    }
-
-    @Test
-    public void testValidateCaptcha_constraintViolationException() {
-        // 准备参数
-        AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class).setCaptchaVerification(null);
-
-        // mock 验证码打开
-        ReflectUtil.setFieldValue(authService, "captchaEnable", true);
-
-        // 调用,并断言异常
-        assertThrows(ConstraintViolationException.class, () -> authService.validateCaptcha(reqVO),
-                "验证码不能为空");
-    }
-
-
-    @Test
-    public void testCaptcha_fail() {
-        // 准备参数
-        AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class);
-
-        // mock 验证码打开
-        ReflectUtil.setFieldValue(authService, "captchaEnable", true);
-        // mock 验证通过
-        when(captchaService.verification(argThat(captchaVO -> {
-            assertEquals(reqVO.getCaptchaVerification(), captchaVO.getCaptchaVerification());
-            return true;
-        }))).thenReturn(ResponseModel.errorMsg("就是不对"));
-
-        // 调用, 并断言异常
-        assertServiceException(() -> authService.validateCaptcha(reqVO), AUTH_LOGIN_CAPTCHA_CODE_ERROR, "就是不对");
-        // 校验调用参数
-        verify(loginLogService).createLoginLog(
-                argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType())
-                        && o.getResult().equals(LoginResultEnum.CAPTCHA_CODE_ERROR.getResult()))
-        );
-    }
-
-    @Test
-    public void testRefreshToken() {
-        // 准备参数
-        String refreshToken = randomString();
-        // mock 方法
-        OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class);
-        when(oauth2TokenService.refreshAccessToken(eq(refreshToken), eq("default")))
-                .thenReturn(accessTokenDO);
-
-        // 调用
-        AuthLoginRespVO loginRespVO = authService.refreshToken(refreshToken);
-        // 断言
-        assertPojoEquals(accessTokenDO, loginRespVO);
-    }
-
-    @Test
-    public void testLogout_success() {
-        // 准备参数
-        String token = randomString();
-        // mock
-        OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class, o -> o.setUserId(1L)
-                .setUserType(UserTypeEnum.ADMIN.getValue()));
-        when(oauth2TokenService.removeAccessToken(eq(token))).thenReturn(accessTokenDO);
-
-        // 调用
-        authService.logout(token, LoginLogTypeEnum.LOGOUT_SELF.getType());
-        // 校验调用参数
-        verify(loginLogService).createLoginLog(
-                argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGOUT_SELF.getType())
-                        && o.getResult().equals(LoginResultEnum.SUCCESS.getResult()))
-        );
-        // 调用,并校验
-
-    }
-
-    @Test
-    public void testLogout_fail() {
-        // 准备参数
-        String token = randomString();
-
-        // 调用
-        authService.logout(token, LoginLogTypeEnum.LOGOUT_SELF.getType());
-        // 校验调用参数
-        verify(loginLogService, never()).createLoginLog(any());
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/dept/DeptServiceImplTest.java b/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/dept/DeptServiceImplTest.java
deleted file mode 100644
index 9fa3be4..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/dept/DeptServiceImplTest.java
+++ /dev/null
@@ -1,296 +0,0 @@
-package com.iailab.module.system.service.dept;
-
-import com.iailab.framework.common.enums.CommonStatusEnum;
-import com.iailab.framework.common.util.object.ObjectUtils;
-import com.iailab.framework.test.core.ut.BaseDbUnitTest;
-import com.iailab.module.system.controller.admin.dept.vo.dept.DeptListReqVO;
-import com.iailab.module.system.controller.admin.dept.vo.dept.DeptSaveReqVO;
-import com.iailab.module.system.dal.dataobject.dept.DeptDO;
-import com.iailab.module.system.dal.mysql.dept.DeptMapper;
-import org.junit.jupiter.api.Test;
-import org.springframework.context.annotation.Import;
-
-import javax.annotation.Resource;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Set;
-
-import static com.iailab.framework.test.core.util.AssertUtils.assertPojoEquals;
-import static com.iailab.framework.test.core.util.AssertUtils.assertServiceException;
-import static com.iailab.framework.test.core.util.RandomUtils.*;
-import static com.iailab.module.system.enums.ErrorCodeConstants.*;
-import static java.util.Collections.singletonList;
-import static org.junit.jupiter.api.Assertions.*;
-
-/**
- * {@link DeptServiceImpl} 的单元测试类
- *
- * @author niudehua
- */
-@Import(DeptServiceImpl.class)
-public class DeptServiceImplTest extends BaseDbUnitTest {
-
-    @Resource
-    private DeptServiceImpl deptService;
-    @Resource
-    private DeptMapper deptMapper;
-
-    @Test
-    public void testCreateDept() {
-        // 准备参数
-        DeptSaveReqVO reqVO = randomPojo(DeptSaveReqVO.class, o -> {
-            o.setId(null); // 防止 id 被设置
-            o.setParentId(DeptDO.PARENT_ID_ROOT);
-            o.setStatus(randomCommonStatus());
-        });
-
-        // 调用
-        Long deptId = deptService.createDept(reqVO);
-        // 断言
-        assertNotNull(deptId);
-        // 校验记录的属性是否正确
-        DeptDO deptDO = deptMapper.selectById(deptId);
-        assertPojoEquals(reqVO, deptDO, "id");
-    }
-
-    @Test
-    public void testUpdateDept() {
-        // mock 数据
-        DeptDO dbDeptDO = randomPojo(DeptDO.class, o -> o.setStatus(randomCommonStatus()));
-        deptMapper.insert(dbDeptDO);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        DeptSaveReqVO reqVO = randomPojo(DeptSaveReqVO.class, o -> {
-            // 设置更新的 ID
-            o.setParentId(DeptDO.PARENT_ID_ROOT);
-            o.setId(dbDeptDO.getId());
-            o.setStatus(randomCommonStatus());
-        });
-
-        // 调用
-        deptService.updateDept(reqVO);
-        // 校验是否更新正确
-        DeptDO deptDO = deptMapper.selectById(reqVO.getId()); // 获取最新的
-        assertPojoEquals(reqVO, deptDO);
-    }
-
-    @Test
-    public void testDeleteDept_success() {
-        // mock 数据
-        DeptDO dbDeptDO = randomPojo(DeptDO.class);
-        deptMapper.insert(dbDeptDO);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        Long id = dbDeptDO.getId();
-
-        // 调用
-        deptService.deleteDept(id);
-        // 校验数据不存在了
-        assertNull(deptMapper.selectById(id));
-    }
-
-    @Test
-    public void testDeleteDept_exitsChildren() {
-        // mock 数据
-        DeptDO parentDept = randomPojo(DeptDO.class);
-        deptMapper.insert(parentDept);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        DeptDO childrenDeptDO = randomPojo(DeptDO.class, o -> {
-            o.setParentId(parentDept.getId());
-            o.setStatus(randomCommonStatus());
-        });
-        // 插入子部门
-        deptMapper.insert(childrenDeptDO);
-
-        // 调用, 并断言异常
-        assertServiceException(() -> deptService.deleteDept(parentDept.getId()), DEPT_EXITS_CHILDREN);
-    }
-
-    @Test
-    public void testValidateDeptExists_notFound() {
-        // 准备参数
-        Long id = randomLongId();
-
-        // 调用, 并断言异常
-        assertServiceException(() -> deptService.validateDeptExists(id), DEPT_NOT_FOUND);
-    }
-
-    @Test
-    public void testValidateParentDept_parentError() {
-        // 准备参数
-        Long id = randomLongId();
-
-        // 调用, 并断言异常
-        assertServiceException(() -> deptService.validateParentDept(id, id),
-                DEPT_PARENT_ERROR);
-    }
-
-    @Test
-    public void testValidateParentDept_parentIsChild() {
-        // mock 数据(父节点)
-        DeptDO parentDept = randomPojo(DeptDO.class);
-        deptMapper.insert(parentDept);
-        // mock 数据(子节点)
-        DeptDO childDept = randomPojo(DeptDO.class, o -> {
-            o.setParentId(parentDept.getId());
-        });
-        deptMapper.insert(childDept);
-
-        // 准备参数
-        Long id = parentDept.getId();
-        Long parentId = childDept.getId();
-
-        // 调用, 并断言异常
-        assertServiceException(() -> deptService.validateParentDept(id, parentId), DEPT_PARENT_IS_CHILD);
-    }
-
-    @Test
-    public void testValidateNameUnique_duplicate() {
-        // mock 数据
-        DeptDO deptDO = randomPojo(DeptDO.class);
-        deptMapper.insert(deptDO);
-
-        // 准备参数
-        Long id = randomLongId();
-        Long parentId = deptDO.getParentId();
-        String name = deptDO.getName();
-
-        // 调用, 并断言异常
-        assertServiceException(() -> deptService.validateDeptNameUnique(id, parentId, name),
-                DEPT_NAME_DUPLICATE);
-    }
-
-    @Test
-    public void testGetDept() {
-        // mock 数据
-        DeptDO deptDO = randomPojo(DeptDO.class);
-        deptMapper.insert(deptDO);
-        // 准备参数
-        Long id = deptDO.getId();
-
-        // 调用
-        DeptDO dbDept = deptService.getDept(id);
-        // 断言
-        assertEquals(deptDO, dbDept);
-    }
-
-    @Test
-    public void testGetDeptList_ids() {
-        // mock 数据
-        DeptDO deptDO01 = randomPojo(DeptDO.class);
-        deptMapper.insert(deptDO01);
-        DeptDO deptDO02 = randomPojo(DeptDO.class);
-        deptMapper.insert(deptDO02);
-        // 准备参数
-        List<Long> ids = Arrays.asList(deptDO01.getId(), deptDO02.getId());
-
-        // 调用
-        List<DeptDO> deptDOList = deptService.getDeptList(ids);
-        // 断言
-        assertEquals(2, deptDOList.size());
-        assertEquals(deptDO01, deptDOList.get(0));
-        assertEquals(deptDO02, deptDOList.get(1));
-    }
-
-    @Test
-    public void testGetDeptList_reqVO() {
-        // mock 数据
-        DeptDO dept = randomPojo(DeptDO.class, o -> { // 等会查询到
-            o.setName("开发部");
-            o.setStatus(CommonStatusEnum.ENABLE.getStatus());
-        });
-        deptMapper.insert(dept);
-        // 测试 name 不匹配
-        deptMapper.insert(ObjectUtils.cloneIgnoreId(dept, o -> o.setName("发")));
-        // 测试 status 不匹配
-        deptMapper.insert(ObjectUtils.cloneIgnoreId(dept, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
-        // 准备参数
-        DeptListReqVO reqVO = new DeptListReqVO();
-        reqVO.setName("开");
-        reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
-
-        // 调用
-        List<DeptDO> sysDeptDOS = deptService.getDeptList(reqVO);
-        // 断言
-        assertEquals(1, sysDeptDOS.size());
-        assertPojoEquals(dept, sysDeptDOS.get(0));
-    }
-
-    @Test
-    public void testGetChildDeptList() {
-        // mock 数据(1 级别子节点)
-        DeptDO dept1 = randomPojo(DeptDO.class, o -> o.setName("1"));
-        deptMapper.insert(dept1);
-        DeptDO dept2 = randomPojo(DeptDO.class, o -> o.setName("2"));
-        deptMapper.insert(dept2);
-        // mock 数据(2 级子节点)
-        DeptDO dept1a = randomPojo(DeptDO.class, o -> o.setName("1-a").setParentId(dept1.getId()));
-        deptMapper.insert(dept1a);
-        DeptDO dept2a = randomPojo(DeptDO.class, o -> o.setName("2-a").setParentId(dept2.getId()));
-        deptMapper.insert(dept2a);
-        // 准备参数
-        Long id = dept1.getParentId();
-
-        // 调用
-        List<DeptDO> result = deptService.getChildDeptList(id);
-        // 断言
-        assertEquals(result.size(), 2);
-        assertPojoEquals(dept1, result.get(0));
-        assertPojoEquals(dept1a, result.get(1));
-    }
-
-    @Test
-    public void testGetChildDeptListFromCache() {
-        // mock 数据(1 级别子节点)
-        DeptDO dept1 = randomPojo(DeptDO.class, o -> o.setName("1"));
-        deptMapper.insert(dept1);
-        DeptDO dept2 = randomPojo(DeptDO.class, o -> o.setName("2"));
-        deptMapper.insert(dept2);
-        // mock 数据(2 级子节点)
-        DeptDO dept1a = randomPojo(DeptDO.class, o -> o.setName("1-a").setParentId(dept1.getId()));
-        deptMapper.insert(dept1a);
-        DeptDO dept2a = randomPojo(DeptDO.class, o -> o.setName("2-a").setParentId(dept2.getId()));
-        deptMapper.insert(dept2a);
-        // 准备参数
-        Long id = dept1.getParentId();
-
-        // 调用
-        Set<Long> result = deptService.getChildDeptIdListFromCache(id);
-        // 断言
-        assertEquals(result.size(), 2);
-        assertTrue(result.contains(dept1.getId()));
-        assertTrue(result.contains(dept1a.getId()));
-    }
-
-    @Test
-    public void testValidateDeptList_success() {
-        // mock 数据
-        DeptDO deptDO = randomPojo(DeptDO.class).setStatus(CommonStatusEnum.ENABLE.getStatus());
-        deptMapper.insert(deptDO);
-        // 准备参数
-        List<Long> ids = singletonList(deptDO.getId());
-
-        // 调用,无需断言
-        deptService.validateDeptList(ids);
-    }
-
-    @Test
-    public void testValidateDeptList_notFound() {
-        // 准备参数
-        List<Long> ids = singletonList(randomLongId());
-
-        // 调用, 并断言异常
-        assertServiceException(() -> deptService.validateDeptList(ids), DEPT_NOT_FOUND);
-    }
-
-    @Test
-    public void testValidateDeptList_notEnable() {
-        // mock 数据
-        DeptDO deptDO = randomPojo(DeptDO.class).setStatus(CommonStatusEnum.DISABLE.getStatus());
-        deptMapper.insert(deptDO);
-        // 准备参数
-        List<Long> ids = singletonList(deptDO.getId());
-
-        // 调用, 并断言异常
-        assertServiceException(() -> deptService.validateDeptList(ids), DEPT_NOT_ENABLE, deptDO.getName());
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/dept/PostServiceImplTest.java b/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/dept/PostServiceImplTest.java
deleted file mode 100644
index 9de154a..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/dept/PostServiceImplTest.java
+++ /dev/null
@@ -1,248 +0,0 @@
-package com.iailab.module.system.service.dept;
-
-import com.iailab.framework.common.enums.CommonStatusEnum;
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.framework.common.util.collection.ArrayUtils;
-import com.iailab.framework.test.core.ut.BaseDbUnitTest;
-import com.iailab.module.system.controller.admin.dept.vo.post.PostPageReqVO;
-import com.iailab.module.system.controller.admin.dept.vo.post.PostSaveReqVO;
-import com.iailab.module.system.dal.dataobject.dept.PostDO;
-import com.iailab.module.system.dal.mysql.dept.PostMapper;
-import org.junit.jupiter.api.Test;
-import org.springframework.context.annotation.Import;
-
-import javax.annotation.Resource;
-import java.util.Arrays;
-import java.util.List;
-import java.util.function.Consumer;
-
-import static cn.hutool.core.util.RandomUtil.randomEle;
-import static com.iailab.framework.common.util.object.ObjectUtils.cloneIgnoreId;
-import static com.iailab.framework.test.core.util.AssertUtils.assertPojoEquals;
-import static com.iailab.framework.test.core.util.AssertUtils.assertServiceException;
-import static com.iailab.framework.test.core.util.RandomUtils.*;
-import static com.iailab.module.system.enums.ErrorCodeConstants.*;
-import static java.util.Collections.singletonList;
-import static org.junit.jupiter.api.Assertions.*;
-
-/**
- * {@link PostServiceImpl} 的单元测试类
- *
- * @author niudehua
- */
-@Import(PostServiceImpl.class)
-public class PostServiceImplTest extends BaseDbUnitTest {
-
-    @Resource
-    private PostServiceImpl postService;
-
-    @Resource
-    private PostMapper postMapper;
-
-    @Test
-    public void testCreatePost_success() {
-        // 准备参数
-        PostSaveReqVO reqVO = randomPojo(PostSaveReqVO.class,
-                o -> o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()))
-                .setId(null); // 防止 id 被设置
-        // 调用
-        Long postId = postService.createPost(reqVO);
-
-        // 断言
-        assertNotNull(postId);
-        // 校验记录的属性是否正确
-        PostDO post = postMapper.selectById(postId);
-        assertPojoEquals(reqVO, post, "id");
-    }
-
-    @Test
-    public void testUpdatePost_success() {
-        // mock 数据
-        PostDO postDO = randomPostDO();
-        postMapper.insert(postDO);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        PostSaveReqVO reqVO = randomPojo(PostSaveReqVO.class, o -> {
-            // 设置更新的 ID
-            o.setId(postDO.getId());
-            o.setStatus(randomEle(CommonStatusEnum.values()).getStatus());
-        });
-
-        // 调用
-        postService.updatePost(reqVO);
-        // 校验是否更新正确
-        PostDO post = postMapper.selectById(reqVO.getId());
-        assertPojoEquals(reqVO, post);
-    }
-
-    @Test
-    public void testDeletePost_success() {
-        // mock 数据
-        PostDO postDO = randomPostDO();
-        postMapper.insert(postDO);
-        // 准备参数
-        Long id = postDO.getId();
-
-        // 调用
-        postService.deletePost(id);
-        assertNull(postMapper.selectById(id));
-    }
-
-    @Test
-    public void testValidatePost_notFoundForDelete() {
-        // 准备参数
-        Long id = randomLongId();
-
-        // 调用, 并断言异常
-        assertServiceException(() -> postService.deletePost(id), POST_NOT_FOUND);
-    }
-
-    @Test
-    public void testValidatePost_nameDuplicateForCreate() {
-        // mock 数据
-        PostDO postDO = randomPostDO();
-        postMapper.insert(postDO);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        PostSaveReqVO reqVO = randomPojo(PostSaveReqVO.class,
-            // 模拟 name 重复
-            o -> o.setName(postDO.getName()));
-        assertServiceException(() -> postService.createPost(reqVO), POST_NAME_DUPLICATE);
-    }
-
-    @Test
-    public void testValidatePost_codeDuplicateForUpdate() {
-        // mock 数据
-        PostDO postDO = randomPostDO();
-        postMapper.insert(postDO);
-        // mock 数据:稍后模拟重复它的 code
-        PostDO codePostDO = randomPostDO();
-        postMapper.insert(codePostDO);
-        // 准备参数
-        PostSaveReqVO reqVO = randomPojo(PostSaveReqVO.class, o -> {
-            // 设置更新的 ID
-            o.setId(postDO.getId());
-            // 模拟 code 重复
-            o.setCode(codePostDO.getCode());
-        });
-
-        // 调用, 并断言异常
-        assertServiceException(() -> postService.updatePost(reqVO), POST_CODE_DUPLICATE);
-    }
-
-    @Test
-    public void testGetPostPage() {
-        // mock 数据
-        PostDO postDO = randomPojo(PostDO.class, o -> {
-            o.setName("码仔");
-            o.setStatus(CommonStatusEnum.ENABLE.getStatus());
-        });
-        postMapper.insert(postDO);
-        // 测试 name 不匹配
-        postMapper.insert(cloneIgnoreId(postDO, o -> o.setName("程序员")));
-        // 测试 status 不匹配
-        postMapper.insert(cloneIgnoreId(postDO, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
-        // 准备参数
-        PostPageReqVO reqVO = new PostPageReqVO();
-        reqVO.setName("码");
-        reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
-
-        // 调用
-        PageResult<PostDO> pageResult = postService.getPostPage(reqVO);
-        // 断言
-        assertEquals(1, pageResult.getTotal());
-        assertEquals(1, pageResult.getList().size());
-        assertPojoEquals(postDO, pageResult.getList().get(0));
-    }
-
-    @Test
-    public void testGetPostList() {
-        // mock 数据
-        PostDO postDO01 = randomPojo(PostDO.class);
-        postMapper.insert(postDO01);
-        // 测试 id 不匹配
-        PostDO postDO02 = randomPojo(PostDO.class);
-        postMapper.insert(postDO02);
-        // 准备参数
-        List<Long> ids = singletonList(postDO01.getId());
-
-        // 调用
-        List<PostDO> list = postService.getPostList(ids);
-        // 断言
-        assertEquals(1, list.size());
-        assertPojoEquals(postDO01, list.get(0));
-    }
-
-    @Test
-    public void testGetPostList_idsAndStatus() {
-        // mock 数据
-        PostDO postDO01 = randomPojo(PostDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus()));
-        postMapper.insert(postDO01);
-        // 测试 status 不匹配
-        PostDO postDO02 = randomPojo(PostDO.class, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()));
-        postMapper.insert(postDO02);
-        // 准备参数
-        List<Long> ids = Arrays.asList(postDO01.getId(), postDO02.getId());
-
-        // 调用
-        List<PostDO> list = postService.getPostList(ids, singletonList(CommonStatusEnum.ENABLE.getStatus()));
-        // 断言
-        assertEquals(1, list.size());
-        assertPojoEquals(postDO01, list.get(0));
-    }
-
-    @Test
-    public void testGetPost() {
-        // mock 数据
-        PostDO dbPostDO = randomPostDO();
-        postMapper.insert(dbPostDO);
-        // 准备参数
-        Long id = dbPostDO.getId();
-        // 调用
-        PostDO post = postService.getPost(id);
-        // 断言
-        assertNotNull(post);
-        assertPojoEquals(dbPostDO, post);
-    }
-
-    @Test
-    public void testValidatePostList_success() {
-        // mock 数据
-        PostDO postDO = randomPostDO().setStatus(CommonStatusEnum.ENABLE.getStatus());
-        postMapper.insert(postDO);
-        // 准备参数
-        List<Long> ids = singletonList(postDO.getId());
-
-        // 调用,无需断言
-        postService.validatePostList(ids);
-    }
-
-    @Test
-    public void testValidatePostList_notFound() {
-        // 准备参数
-        List<Long> ids = singletonList(randomLongId());
-
-        // 调用, 并断言异常
-        assertServiceException(() -> postService.validatePostList(ids), POST_NOT_FOUND);
-    }
-
-    @Test
-    public void testValidatePostList_notEnable() {
-        // mock 数据
-        PostDO postDO = randomPostDO().setStatus(CommonStatusEnum.DISABLE.getStatus());
-        postMapper.insert(postDO);
-        // 准备参数
-        List<Long> ids = singletonList(postDO.getId());
-
-        // 调用, 并断言异常
-        assertServiceException(() -> postService.validatePostList(ids), POST_NOT_ENABLE,
-                postDO.getName());
-    }
-
-    @SafeVarargs
-    private static PostDO randomPostDO(Consumer<PostDO>... consumers) {
-        Consumer<PostDO> consumer = (o) -> {
-            o.setStatus(randomCommonStatus()); // 保证 status 的范围
-        };
-        return randomPojo(PostDO.class, ArrayUtils.append(consumer, consumers));
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/dict/DictDataServiceImplTest.java b/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/dict/DictDataServiceImplTest.java
deleted file mode 100644
index 5f4e8f0..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/dict/DictDataServiceImplTest.java
+++ /dev/null
@@ -1,352 +0,0 @@
-package com.iailab.module.system.service.dict;
-
-import com.iailab.framework.common.enums.CommonStatusEnum;
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.framework.common.util.collection.ArrayUtils;
-import com.iailab.framework.test.core.ut.BaseDbUnitTest;
-import com.iailab.module.system.controller.admin.dict.vo.data.DictDataPageReqVO;
-import com.iailab.module.system.controller.admin.dict.vo.data.DictDataSaveReqVO;
-import com.iailab.module.system.dal.dataobject.dict.DictDataDO;
-import com.iailab.module.system.dal.dataobject.dict.DictTypeDO;
-import com.iailab.module.system.dal.mysql.dict.DictDataMapper;
-import org.junit.jupiter.api.Test;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.context.annotation.Import;
-
-import javax.annotation.Resource;
-import java.util.List;
-import java.util.function.Consumer;
-
-import static com.iailab.framework.common.util.object.ObjectUtils.cloneIgnoreId;
-import static com.iailab.framework.test.core.util.AssertUtils.assertPojoEquals;
-import static com.iailab.framework.test.core.util.AssertUtils.assertServiceException;
-import static com.iailab.framework.test.core.util.RandomUtils.*;
-import static com.iailab.module.system.enums.ErrorCodeConstants.*;
-import static java.util.Collections.singletonList;
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.when;
-
-@Import(DictDataServiceImpl.class)
-public class DictDataServiceImplTest extends BaseDbUnitTest {
-
-    @Resource
-    private DictDataServiceImpl dictDataService;
-
-    @Resource
-    private DictDataMapper dictDataMapper;
-    @MockBean
-    private DictTypeService dictTypeService;
-
-    @Test
-    public void testGetDictDataList() {
-        // mock 数据
-        DictDataDO dictDataDO01 = randomDictDataDO().setDictType("yunai").setSort(2)
-                .setStatus(CommonStatusEnum.ENABLE.getStatus());
-        dictDataMapper.insert(dictDataDO01);
-        DictDataDO dictDataDO02 = randomDictDataDO().setDictType("yunai").setSort(1)
-                .setStatus(CommonStatusEnum.ENABLE.getStatus());
-        dictDataMapper.insert(dictDataDO02);
-        DictDataDO dictDataDO03 = randomDictDataDO().setDictType("yunai").setSort(3)
-                .setStatus(CommonStatusEnum.DISABLE.getStatus());
-        dictDataMapper.insert(dictDataDO03);
-        DictDataDO dictDataDO04 = randomDictDataDO().setDictType("yunai2").setSort(3)
-                .setStatus(CommonStatusEnum.DISABLE.getStatus());
-        dictDataMapper.insert(dictDataDO04);
-        // 准备参数
-        Integer status = CommonStatusEnum.ENABLE.getStatus();
-        String dictType = "yunai";
-
-        // 调用
-        List<DictDataDO> dictDataDOList = dictDataService.getDictDataList(status, dictType);
-        // 断言
-        assertEquals(2, dictDataDOList.size());
-        assertPojoEquals(dictDataDO02, dictDataDOList.get(0));
-        assertPojoEquals(dictDataDO01, dictDataDOList.get(1));
-    }
-
-    @Test
-    public void testGetDictDataPage() {
-        // mock 数据
-        DictDataDO dbDictData = randomPojo(DictDataDO.class, o -> { // 等会查询到
-            o.setLabel("iailab");
-            o.setDictType("yunai");
-            o.setStatus(CommonStatusEnum.ENABLE.getStatus());
-        });
-        dictDataMapper.insert(dbDictData);
-        // 测试 label 不匹配
-        dictDataMapper.insert(cloneIgnoreId(dbDictData, o -> o.setLabel("艿")));
-        // 测试 dictType 不匹配
-        dictDataMapper.insert(cloneIgnoreId(dbDictData, o -> o.setDictType("nai")));
-        // 测试 status 不匹配
-        dictDataMapper.insert(cloneIgnoreId(dbDictData, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
-        // 准备参数
-        DictDataPageReqVO reqVO = new DictDataPageReqVO();
-        reqVO.setLabel("芋");
-        reqVO.setDictType("yunai");
-        reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
-
-        // 调用
-        PageResult<DictDataDO> pageResult = dictDataService.getDictDataPage(reqVO);
-        // 断言
-        assertEquals(1, pageResult.getTotal());
-        assertEquals(1, pageResult.getList().size());
-        assertPojoEquals(dbDictData, pageResult.getList().get(0));
-    }
-
-    @Test
-    public void testGetDictData() {
-        // mock 数据
-        DictDataDO dbDictData = randomDictDataDO();
-        dictDataMapper.insert(dbDictData);
-        // 准备参数
-        Long id = dbDictData.getId();
-
-        // 调用
-        DictDataDO dictData = dictDataService.getDictData(id);
-        // 断言
-        assertPojoEquals(dbDictData, dictData);
-    }
-
-    @Test
-    public void testCreateDictData_success() {
-        // 准备参数
-        DictDataSaveReqVO reqVO = randomPojo(DictDataSaveReqVO.class,
-                o -> o.setStatus(randomCommonStatus()))
-                .setId(null); // 防止 id 被赋值
-        // mock 方法
-        when(dictTypeService.getDictType(eq(reqVO.getDictType()))).thenReturn(randomDictTypeDO(reqVO.getDictType()));
-
-        // 调用
-        Long dictDataId = dictDataService.createDictData(reqVO);
-        // 断言
-        assertNotNull(dictDataId);
-        // 校验记录的属性是否正确
-        DictDataDO dictData = dictDataMapper.selectById(dictDataId);
-        assertPojoEquals(reqVO, dictData, "id");
-    }
-
-    @Test
-    public void testUpdateDictData_success() {
-        // mock 数据
-        DictDataDO dbDictData = randomDictDataDO();
-        dictDataMapper.insert(dbDictData);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        DictDataSaveReqVO reqVO = randomPojo(DictDataSaveReqVO.class, o -> {
-            o.setId(dbDictData.getId()); // 设置更新的 ID
-            o.setStatus(randomCommonStatus());
-        });
-        // mock 方法,字典类型
-        when(dictTypeService.getDictType(eq(reqVO.getDictType()))).thenReturn(randomDictTypeDO(reqVO.getDictType()));
-
-        // 调用
-        dictDataService.updateDictData(reqVO);
-        // 校验是否更新正确
-        DictDataDO dictData = dictDataMapper.selectById(reqVO.getId()); // 获取最新的
-        assertPojoEquals(reqVO, dictData);
-    }
-
-    @Test
-    public void testDeleteDictData_success() {
-        // mock 数据
-        DictDataDO dbDictData = randomDictDataDO();
-        dictDataMapper.insert(dbDictData);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        Long id = dbDictData.getId();
-
-        // 调用
-        dictDataService.deleteDictData(id);
-        // 校验数据不存在了
-        assertNull(dictDataMapper.selectById(id));
-    }
-
-    @Test
-    public void testValidateDictDataExists_success() {
-        // mock 数据
-        DictDataDO dbDictData = randomDictDataDO();
-        dictDataMapper.insert(dbDictData);// @Sql: 先插入出一条存在的数据
-
-        // 调用成功
-        dictDataService.validateDictDataExists(dbDictData.getId());
-    }
-
-    @Test
-    public void testValidateDictDataExists_notExists() {
-        assertServiceException(() -> dictDataService.validateDictDataExists(randomLongId()), DICT_DATA_NOT_EXISTS);
-    }
-
-    @Test
-    public void testValidateDictTypeExists_success() {
-        // mock 方法,数据类型被禁用
-        String type = randomString();
-        when(dictTypeService.getDictType(eq(type))).thenReturn(randomDictTypeDO(type));
-
-        // 调用, 成功
-        dictDataService.validateDictTypeExists(type);
-    }
-
-    @Test
-    public void testValidateDictTypeExists_notExists() {
-        assertServiceException(() -> dictDataService.validateDictTypeExists(randomString()), DICT_TYPE_NOT_EXISTS);
-    }
-
-    @Test
-    public void testValidateDictTypeExists_notEnable() {
-        // mock 方法,数据类型被禁用
-        String dictType = randomString();
-        when(dictTypeService.getDictType(eq(dictType))).thenReturn(
-                randomPojo(DictTypeDO.class, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
-
-        // 调用, 并断言异常
-        assertServiceException(() -> dictDataService.validateDictTypeExists(dictType), DICT_TYPE_NOT_ENABLE);
-    }
-
-    @Test
-    public void testValidateDictDataValueUnique_success() {
-        // 调用,成功
-        dictDataService.validateDictDataValueUnique(randomLongId(), randomString(), randomString());
-    }
-
-    @Test
-    public void testValidateDictDataValueUnique_valueDuplicateForCreate() {
-        // 准备参数
-        String dictType = randomString();
-        String value = randomString();
-        // mock 数据
-        dictDataMapper.insert(randomDictDataDO(o -> {
-            o.setDictType(dictType);
-            o.setValue(value);
-        }));
-
-        // 调用,校验异常
-        assertServiceException(() -> dictDataService.validateDictDataValueUnique(null, dictType, value),
-                DICT_DATA_VALUE_DUPLICATE);
-    }
-
-    @Test
-    public void testValidateDictDataValueUnique_valueDuplicateForUpdate() {
-        // 准备参数
-        Long id = randomLongId();
-        String dictType = randomString();
-        String value = randomString();
-        // mock 数据
-        dictDataMapper.insert(randomDictDataDO(o -> {
-            o.setDictType(dictType);
-            o.setValue(value);
-        }));
-
-        // 调用,校验异常
-        assertServiceException(() -> dictDataService.validateDictDataValueUnique(id, dictType, value),
-                DICT_DATA_VALUE_DUPLICATE);
-    }
-
-    @Test
-    public void testGetDictDataCountByDictType() {
-        // mock 数据
-        dictDataMapper.insert(randomDictDataDO(o -> o.setDictType("yunai")));
-        dictDataMapper.insert(randomDictDataDO(o -> o.setDictType("tudou")));
-        dictDataMapper.insert(randomDictDataDO(o -> o.setDictType("yunai")));
-        // 准备参数
-        String dictType = "yunai";
-
-        // 调用
-        long count = dictDataService.getDictDataCountByDictType(dictType);
-        // 校验
-        assertEquals(2L, count);
-    }
-
-    @Test
-    public void testValidateDictDataList_success() {
-        // mock 数据
-        DictDataDO dictDataDO = randomDictDataDO().setStatus(CommonStatusEnum.ENABLE.getStatus());
-        dictDataMapper.insert(dictDataDO);
-        // 准备参数
-        String dictType = dictDataDO.getDictType();
-        List<String> values = singletonList(dictDataDO.getValue());
-
-        // 调用,无需断言
-        dictDataService.validateDictDataList(dictType, values);
-    }
-
-    @Test
-    public void testValidateDictDataList_notFound() {
-        // 准备参数
-        String dictType = randomString();
-        List<String> values = singletonList(randomString());
-
-        // 调用, 并断言异常
-        assertServiceException(() -> dictDataService.validateDictDataList(dictType, values), DICT_DATA_NOT_EXISTS);
-    }
-
-    @Test
-    public void testValidateDictDataList_notEnable() {
-        // mock 数据
-        DictDataDO dictDataDO = randomDictDataDO().setStatus(CommonStatusEnum.DISABLE.getStatus());
-        dictDataMapper.insert(dictDataDO);
-        // 准备参数
-        String dictType = dictDataDO.getDictType();
-        List<String> values = singletonList(dictDataDO.getValue());
-
-        // 调用, 并断言异常
-        assertServiceException(() -> dictDataService.validateDictDataList(dictType, values),
-                DICT_DATA_NOT_ENABLE, dictDataDO.getLabel());
-    }
-
-    @Test
-    public void testGetDictData_dictType() {
-        // mock 数据
-        DictDataDO dictDataDO = randomDictDataDO().setDictType("yunai").setValue("1");
-        dictDataMapper.insert(dictDataDO);
-        DictDataDO dictDataDO02 = randomDictDataDO().setDictType("yunai").setValue("2");
-        dictDataMapper.insert(dictDataDO02);
-        // 准备参数
-        String dictType = "yunai";
-        String value = "1";
-
-        // 调用
-        DictDataDO dbDictData = dictDataService.getDictData(dictType, value);
-        // 断言
-        assertEquals(dictDataDO, dbDictData);
-    }
-
-    @Test
-    public void testParseDictData() {
-        // mock 数据
-        DictDataDO dictDataDO = randomDictDataDO().setDictType("yunai").setLabel("1");
-        dictDataMapper.insert(dictDataDO);
-        DictDataDO dictDataDO02 = randomDictDataDO().setDictType("yunai").setLabel("2");
-        dictDataMapper.insert(dictDataDO02);
-        // 准备参数
-        String dictType = "yunai";
-        String label = "1";
-
-        // 调用
-        DictDataDO dbDictData = dictDataService.parseDictData(dictType, label);
-        // 断言
-        assertEquals(dictDataDO, dbDictData);
-    }
-
-    // ========== 随机对象 ==========
-
-    @SafeVarargs
-    private static DictDataDO randomDictDataDO(Consumer<DictDataDO>... consumers) {
-        Consumer<DictDataDO> consumer = (o) -> {
-            o.setStatus(randomCommonStatus()); // 保证 status 的范围
-        };
-        return randomPojo(DictDataDO.class, ArrayUtils.append(consumer, consumers));
-    }
-
-    /**
-     * 生成一个有效的字典类型
-     *
-     * @param type 字典类型
-     * @return DictTypeDO 对象
-     */
-    private static DictTypeDO randomDictTypeDO(String type) {
-        return randomPojo(DictTypeDO.class, o -> {
-            o.setType(type);
-            o.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 保证 status 是开启
-        });
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/dict/DictTypeServiceImplTest.java b/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/dict/DictTypeServiceImplTest.java
deleted file mode 100644
index be36bfc..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/dict/DictTypeServiceImplTest.java
+++ /dev/null
@@ -1,271 +0,0 @@
-package com.iailab.module.system.service.dict;
-
-import com.iailab.framework.common.enums.CommonStatusEnum;
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.framework.common.util.collection.ArrayUtils;
-import com.iailab.framework.test.core.ut.BaseDbUnitTest;
-import com.iailab.module.system.controller.admin.dict.vo.type.DictTypePageReqVO;
-import com.iailab.module.system.controller.admin.dict.vo.type.DictTypeSaveReqVO;
-import com.iailab.module.system.dal.dataobject.dict.DictTypeDO;
-import com.iailab.module.system.dal.mysql.dict.DictTypeMapper;
-import org.junit.jupiter.api.Test;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.context.annotation.Import;
-
-import javax.annotation.Resource;
-import java.util.List;
-import java.util.function.Consumer;
-
-import static cn.hutool.core.util.RandomUtil.randomEle;
-import static com.iailab.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
-import static com.iailab.framework.common.util.date.LocalDateTimeUtils.buildTime;
-import static com.iailab.framework.common.util.object.ObjectUtils.cloneIgnoreId;
-import static com.iailab.framework.test.core.util.AssertUtils.assertPojoEquals;
-import static com.iailab.framework.test.core.util.AssertUtils.assertServiceException;
-import static com.iailab.framework.test.core.util.RandomUtils.*;
-import static com.iailab.module.system.enums.ErrorCodeConstants.*;
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.when;
-
-@Import(DictTypeServiceImpl.class)
-public class DictTypeServiceImplTest extends BaseDbUnitTest {
-
-    @Resource
-    private DictTypeServiceImpl dictTypeService;
-
-    @Resource
-    private DictTypeMapper dictTypeMapper;
-    @MockBean
-    private DictDataService dictDataService;
-
-    @Test
-    public void testGetDictTypePage() {
-       // mock 数据
-       DictTypeDO dbDictType = randomPojo(DictTypeDO.class, o -> { // 等会查询到
-           o.setName("yunai");
-           o.setType("iailab");
-           o.setStatus(CommonStatusEnum.ENABLE.getStatus());
-           o.setCreateTime(buildTime(2021, 1, 15));
-       });
-       dictTypeMapper.insert(dbDictType);
-       // 测试 name 不匹配
-       dictTypeMapper.insert(cloneIgnoreId(dbDictType, o -> o.setName("tudou")));
-       // 测试 type 不匹配
-       dictTypeMapper.insert(cloneIgnoreId(dbDictType, o -> o.setType("土豆")));
-       // 测试 status 不匹配
-       dictTypeMapper.insert(cloneIgnoreId(dbDictType, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
-       // 测试 createTime 不匹配
-       dictTypeMapper.insert(cloneIgnoreId(dbDictType, o -> o.setCreateTime(buildTime(2021, 1, 1))));
-       // 准备参数
-       DictTypePageReqVO reqVO = new DictTypePageReqVO();
-       reqVO.setName("nai");
-       reqVO.setType("艿");
-       reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
-       reqVO.setCreateTime(buildBetweenTime(2021, 1, 10, 2021, 1, 20));
-
-       // 调用
-       PageResult<DictTypeDO> pageResult = dictTypeService.getDictTypePage(reqVO);
-       // 断言
-       assertEquals(1, pageResult.getTotal());
-       assertEquals(1, pageResult.getList().size());
-       assertPojoEquals(dbDictType, pageResult.getList().get(0));
-    }
-
-    @Test
-    public void testGetDictType_id() {
-        // mock 数据
-        DictTypeDO dbDictType = randomDictTypeDO();
-        dictTypeMapper.insert(dbDictType);
-        // 准备参数
-        Long id = dbDictType.getId();
-
-        // 调用
-        DictTypeDO dictType = dictTypeService.getDictType(id);
-        // 断言
-        assertNotNull(dictType);
-        assertPojoEquals(dbDictType, dictType);
-    }
-
-    @Test
-    public void testGetDictType_type() {
-        // mock 数据
-        DictTypeDO dbDictType = randomDictTypeDO();
-        dictTypeMapper.insert(dbDictType);
-        // 准备参数
-        String type = dbDictType.getType();
-
-        // 调用
-        DictTypeDO dictType = dictTypeService.getDictType(type);
-        // 断言
-        assertNotNull(dictType);
-        assertPojoEquals(dbDictType, dictType);
-    }
-
-    @Test
-    public void testCreateDictType_success() {
-        // 准备参数
-        DictTypeSaveReqVO reqVO = randomPojo(DictTypeSaveReqVO.class,
-                o -> o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()))
-                .setId(null); // 避免 id 被赋值
-
-        // 调用
-        Long dictTypeId = dictTypeService.createDictType(reqVO);
-        // 断言
-        assertNotNull(dictTypeId);
-        // 校验记录的属性是否正确
-        DictTypeDO dictType = dictTypeMapper.selectById(dictTypeId);
-        assertPojoEquals(reqVO, dictType, "id");
-    }
-
-    @Test
-    public void testUpdateDictType_success() {
-        // mock 数据
-        DictTypeDO dbDictType = randomDictTypeDO();
-        dictTypeMapper.insert(dbDictType);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        DictTypeSaveReqVO reqVO = randomPojo(DictTypeSaveReqVO.class, o -> {
-            o.setId(dbDictType.getId()); // 设置更新的 ID
-            o.setStatus(randomEle(CommonStatusEnum.values()).getStatus());
-        });
-
-        // 调用
-        dictTypeService.updateDictType(reqVO);
-        // 校验是否更新正确
-        DictTypeDO dictType = dictTypeMapper.selectById(reqVO.getId()); // 获取最新的
-        assertPojoEquals(reqVO, dictType);
-    }
-
-    @Test
-    public void testDeleteDictType_success() {
-        // mock 数据
-        DictTypeDO dbDictType = randomDictTypeDO();
-        dictTypeMapper.insert(dbDictType);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        Long id = dbDictType.getId();
-
-        // 调用
-        dictTypeService.deleteDictType(id);
-        // 校验数据不存在了
-        assertNull(dictTypeMapper.selectById(id));
-    }
-
-    @Test
-    public void testDeleteDictType_hasChildren() {
-        // mock 数据
-        DictTypeDO dbDictType = randomDictTypeDO();
-        dictTypeMapper.insert(dbDictType);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        Long id = dbDictType.getId();
-        // mock 方法
-        when(dictDataService.getDictDataCountByDictType(eq(dbDictType.getType()))).thenReturn(1L);
-
-        // 调用, 并断言异常
-        assertServiceException(() -> dictTypeService.deleteDictType(id), DICT_TYPE_HAS_CHILDREN);
-    }
-
-    @Test
-    public void testGetDictTypeList() {
-        // 准备参数
-        DictTypeDO dictTypeDO01 = randomDictTypeDO();
-        dictTypeMapper.insert(dictTypeDO01);
-        DictTypeDO dictTypeDO02 = randomDictTypeDO();
-        dictTypeMapper.insert(dictTypeDO02);
-        // mock 方法
-
-        // 调用
-        List<DictTypeDO> dictTypeDOList = dictTypeService.getDictTypeList();
-        // 断言
-        assertEquals(2, dictTypeDOList.size());
-        assertPojoEquals(dictTypeDO01, dictTypeDOList.get(0));
-        assertPojoEquals(dictTypeDO02, dictTypeDOList.get(1));
-    }
-
-    @Test
-    public void testValidateDictDataExists_success() {
-        // mock 数据
-        DictTypeDO dbDictType = randomDictTypeDO();
-        dictTypeMapper.insert(dbDictType);// @Sql: 先插入出一条存在的数据
-
-        // 调用成功
-        dictTypeService.validateDictTypeExists(dbDictType.getId());
-    }
-
-    @Test
-    public void testValidateDictDataExists_notExists() {
-        assertServiceException(() -> dictTypeService.validateDictTypeExists(randomLongId()), DICT_TYPE_NOT_EXISTS);
-    }
-
-    @Test
-    public void testValidateDictTypeUnique_success() {
-        // 调用,成功
-        dictTypeService.validateDictTypeUnique(randomLongId(), randomString());
-    }
-
-    @Test
-    public void testValidateDictTypeUnique_valueDuplicateForCreate() {
-        // 准备参数
-        String type = randomString();
-        // mock 数据
-        dictTypeMapper.insert(randomDictTypeDO(o -> o.setType(type)));
-
-        // 调用,校验异常
-        assertServiceException(() -> dictTypeService.validateDictTypeUnique(null, type),
-                DICT_TYPE_TYPE_DUPLICATE);
-    }
-
-    @Test
-    public void testValidateDictTypeUnique_valueDuplicateForUpdate() {
-        // 准备参数
-        Long id = randomLongId();
-        String type = randomString();
-        // mock 数据
-        dictTypeMapper.insert(randomDictTypeDO(o -> o.setType(type)));
-
-        // 调用,校验异常
-        assertServiceException(() -> dictTypeService.validateDictTypeUnique(id, type),
-                DICT_TYPE_TYPE_DUPLICATE);
-    }
-
-    @Test
-    public void testValidateDictTypNameUnique_success() {
-        // 调用,成功
-        dictTypeService.validateDictTypeNameUnique(randomLongId(), randomString());
-    }
-
-    @Test
-    public void testValidateDictTypeNameUnique_nameDuplicateForCreate() {
-        // 准备参数
-        String name = randomString();
-        // mock 数据
-        dictTypeMapper.insert(randomDictTypeDO(o -> o.setName(name)));
-
-        // 调用,校验异常
-        assertServiceException(() -> dictTypeService.validateDictTypeNameUnique(null, name),
-                DICT_TYPE_NAME_DUPLICATE);
-    }
-
-    @Test
-    public void testValidateDictTypeNameUnique_nameDuplicateForUpdate() {
-        // 准备参数
-        Long id = randomLongId();
-        String name = randomString();
-        // mock 数据
-        dictTypeMapper.insert(randomDictTypeDO(o -> o.setName(name)));
-
-        // 调用,校验异常
-        assertServiceException(() -> dictTypeService.validateDictTypeNameUnique(id, name),
-                DICT_TYPE_NAME_DUPLICATE);
-    }
-
-    // ========== 随机对象 ==========
-
-    @SafeVarargs
-    private static DictTypeDO randomDictTypeDO(Consumer<DictTypeDO>... consumers) {
-        Consumer<DictTypeDO> consumer = (o) -> {
-            o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围
-        };
-        return randomPojo(DictTypeDO.class, ArrayUtils.append(consumer, consumers));
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/logger/LoginLogServiceImplTest.java b/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/logger/LoginLogServiceImplTest.java
deleted file mode 100644
index e992b1d..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/logger/LoginLogServiceImplTest.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package com.iailab.module.system.service.logger;
-
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.framework.test.core.ut.BaseDbUnitTest;
-import com.iailab.module.system.api.logger.dto.LoginLogCreateReqDTO;
-import com.iailab.module.system.controller.admin.logger.vo.loginlog.LoginLogPageReqVO;
-import com.iailab.module.system.dal.dataobject.logger.LoginLogDO;
-import com.iailab.module.system.dal.mysql.logger.LoginLogMapper;
-import org.junit.jupiter.api.Test;
-import org.springframework.context.annotation.Import;
-
-import javax.annotation.Resource;
-
-import static com.iailab.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
-import static com.iailab.framework.common.util.date.LocalDateTimeUtils.buildTime;
-import static com.iailab.framework.common.util.object.ObjectUtils.cloneIgnoreId;
-import static com.iailab.framework.test.core.util.AssertUtils.assertPojoEquals;
-import static com.iailab.framework.test.core.util.RandomUtils.randomPojo;
-import static com.iailab.module.system.enums.logger.LoginResultEnum.CAPTCHA_CODE_ERROR;
-import static com.iailab.module.system.enums.logger.LoginResultEnum.SUCCESS;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-@Import(LoginLogServiceImpl.class)
-public class LoginLogServiceImplTest extends BaseDbUnitTest {
-
-    @Resource
-    private LoginLogServiceImpl loginLogService;
-
-    @Resource
-    private LoginLogMapper loginLogMapper;
-
-    @Test
-    public void testGetLoginLogPage() {
-        // mock 数据
-        LoginLogDO loginLogDO = randomPojo(LoginLogDO.class, o -> {
-            o.setUserIp("192.168.199.16");
-            o.setUsername("wang");
-            o.setResult(SUCCESS.getResult());
-            o.setCreateTime(buildTime(2021, 3, 6));
-        });
-        loginLogMapper.insert(loginLogDO);
-        // 测试 status 不匹配
-        loginLogMapper.insert(cloneIgnoreId(loginLogDO, o -> o.setResult(CAPTCHA_CODE_ERROR.getResult())));
-        // 测试 ip 不匹配
-        loginLogMapper.insert(cloneIgnoreId(loginLogDO, o -> o.setUserIp("192.168.128.18")));
-        // 测试 username 不匹配
-        loginLogMapper.insert(cloneIgnoreId(loginLogDO, o -> o.setUsername("yunai")));
-        // 测试 createTime 不匹配
-        loginLogMapper.insert(cloneIgnoreId(loginLogDO, o -> o.setCreateTime(buildTime(2021, 2, 6))));
-        // 构造调用参数
-        LoginLogPageReqVO reqVO = new LoginLogPageReqVO();
-        reqVO.setUsername("wang");
-        reqVO.setUserIp("192.168.199");
-        reqVO.setStatus(true);
-        reqVO.setCreateTime(buildBetweenTime(2021, 3, 5, 2021, 3, 7));
-
-        // 调用
-        PageResult<LoginLogDO> pageResult = loginLogService.getLoginLogPage(reqVO);
-        // 断言,只查到了一条符合条件的
-        assertEquals(1, pageResult.getTotal());
-        assertEquals(1, pageResult.getList().size());
-        assertPojoEquals(loginLogDO, pageResult.getList().get(0));
-    }
-
-    @Test
-    public void testCreateLoginLog() {
-        LoginLogCreateReqDTO reqDTO = randomPojo(LoginLogCreateReqDTO.class);
-
-        // 调用
-        loginLogService.createLoginLog(reqDTO);
-        // 断言
-        LoginLogDO loginLogDO = loginLogMapper.selectOne(null);
-        assertPojoEquals(reqDTO, loginLogDO);
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/logger/OperateLogServiceImplTest.java b/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/logger/OperateLogServiceImplTest.java
deleted file mode 100644
index 1041902..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/logger/OperateLogServiceImplTest.java
+++ /dev/null
@@ -1,114 +0,0 @@
-package com.iailab.module.system.service.logger;
-
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.framework.test.core.ut.BaseDbUnitTest;
-import com.iailab.framework.test.core.util.RandomUtils;
-import com.iailab.module.system.api.logger.dto.OperateLogCreateReqDTO;
-import com.iailab.module.system.api.logger.dto.OperateLogPageReqDTO;
-import com.iailab.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO;
-import com.iailab.module.system.dal.dataobject.logger.OperateLogDO;
-import com.iailab.module.system.dal.mysql.logger.OperateLogMapper;
-import org.junit.jupiter.api.Test;
-import org.springframework.context.annotation.Import;
-
-import javax.annotation.Resource;
-
-import static com.iailab.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
-import static com.iailab.framework.common.util.date.LocalDateTimeUtils.buildTime;
-import static com.iailab.framework.common.util.object.ObjectUtils.cloneIgnoreId;
-import static com.iailab.framework.test.core.util.AssertUtils.assertPojoEquals;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-@Import({OperateLogServiceImpl.class})
-public class OperateLogServiceImplTest extends BaseDbUnitTest {
-
-    @Resource
-    private OperateLogService operateLogServiceImpl;
-
-    @Resource
-    private OperateLogMapper operateLogMapper;
-
-    @Test
-    public void testCreateOperateLog() {
-        OperateLogCreateReqDTO reqVO = RandomUtils.randomPojo(OperateLogCreateReqDTO.class);
-
-        // 调研
-        operateLogServiceImpl.createOperateLog(reqVO);
-        // 断言
-        OperateLogDO operateLogDO = operateLogMapper.selectOne(null);
-        assertPojoEquals(reqVO, operateLogDO);
-    }
-
-    @Test
-    public void testGetOperateLogPage_vo() {
-        // 构造操作日志
-        OperateLogDO operateLogDO = RandomUtils.randomPojo(OperateLogDO.class, o -> {
-            o.setUserId(2048L);
-            o.setBizId(999L);
-            o.setType("订单");
-            o.setSubType("创建订单");
-            o.setAction("修改编号为 1 的用户信息");
-            o.setCreateTime(buildTime(2021, 3, 6));
-        });
-        operateLogMapper.insert(operateLogDO);
-        // 测试 userId 不匹配
-        operateLogMapper.insert(cloneIgnoreId(operateLogDO, o -> o.setUserId(1024L)));
-        // 测试 bizId 不匹配
-        operateLogMapper.insert(cloneIgnoreId(operateLogDO, o -> o.setBizId(888L)));
-        // 测试 type 不匹配
-        operateLogMapper.insert(cloneIgnoreId(operateLogDO, o -> o.setType("退款")));
-        // 测试 subType 不匹配
-        operateLogMapper.insert(cloneIgnoreId(operateLogDO, o -> o.setSubType("创建退款")));
-        // 测试 action 不匹配
-        operateLogMapper.insert(cloneIgnoreId(operateLogDO, o -> o.setAction("修改编号为 1 退款信息")));
-        // 测试 createTime 不匹配
-        operateLogMapper.insert(cloneIgnoreId(operateLogDO, o -> o.setCreateTime(buildTime(2021, 2, 6))));
-
-        // 构造调用参数
-        OperateLogPageReqVO reqVO = new OperateLogPageReqVO();
-        reqVO.setUserId(2048L);
-        reqVO.setBizId(999L);
-        reqVO.setType("订");
-        reqVO.setSubType("订单");
-        reqVO.setAction("用户信息");
-        reqVO.setCreateTime(buildBetweenTime(2021, 3, 5, 2021, 3, 7));
-
-        // 调用
-        PageResult<OperateLogDO> pageResult = operateLogServiceImpl.getOperateLogPage(reqVO);
-        // 断言,只查到了一条符合条件的
-        assertEquals(1, pageResult.getTotal());
-        assertEquals(1, pageResult.getList().size());
-        assertPojoEquals(operateLogDO, pageResult.getList().get(0));
-    }
-
-    @Test
-    public void testGetOperateLogPage_dto() {
-        // 构造操作日志
-        OperateLogDO operateLogDO = RandomUtils.randomPojo(OperateLogDO.class, o -> {
-            o.setUserId(2048L);
-            o.setBizId(999L);
-            o.setType("订单");
-        });
-        operateLogMapper.insert(operateLogDO);
-        // 测试 userId 不匹配
-        operateLogMapper.insert(cloneIgnoreId(operateLogDO, o -> o.setUserId(1024L)));
-        // 测试 bizId 不匹配
-        operateLogMapper.insert(cloneIgnoreId(operateLogDO, o -> o.setBizId(888L)));
-        // 测试 type 不匹配
-        operateLogMapper.insert(cloneIgnoreId(operateLogDO, o -> o.setType("退款")));
-
-        // 构造调用参数
-        OperateLogPageReqDTO reqDTO = new OperateLogPageReqDTO();
-        reqDTO.setUserId(2048L);
-        reqDTO.setBizId(999L);
-        reqDTO.setType("订单");
-
-        // 调用
-        PageResult<OperateLogDO> pageResult = operateLogServiceImpl.getOperateLogPage(reqDTO);
-        // 断言,只查到了一条符合条件的
-        assertEquals(1, pageResult.getTotal());
-        assertEquals(1, pageResult.getList().size());
-        assertPojoEquals(operateLogDO, pageResult.getList().get(0));
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/mail/MailAccountServiceImplTest.java b/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/mail/MailAccountServiceImplTest.java
deleted file mode 100644
index 5b218cb..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/mail/MailAccountServiceImplTest.java
+++ /dev/null
@@ -1,179 +0,0 @@
-package com.iailab.module.system.service.mail;
-
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.framework.test.core.ut.BaseDbUnitTest;
-import com.iailab.module.system.controller.admin.mail.vo.account.MailAccountPageReqVO;
-import com.iailab.module.system.controller.admin.mail.vo.account.MailAccountSaveReqVO;
-import com.iailab.module.system.dal.dataobject.mail.MailAccountDO;
-import com.iailab.module.system.dal.mysql.mail.MailAccountMapper;
-import org.junit.jupiter.api.Test;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.context.annotation.Import;
-
-import javax.annotation.Resource;
-import java.util.List;
-
-import static com.iailab.framework.common.util.object.ObjectUtils.cloneIgnoreId;
-import static com.iailab.framework.test.core.util.AssertUtils.assertPojoEquals;
-import static com.iailab.framework.test.core.util.AssertUtils.assertServiceException;
-import static com.iailab.framework.test.core.util.RandomUtils.*;
-import static com.iailab.module.system.enums.ErrorCodeConstants.MAIL_ACCOUNT_NOT_EXISTS;
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.when;
-
-/**
- * {@link MailAccountServiceImpl} 的单元测试类
- *
- * @author iailab
- */
-@Import(MailAccountServiceImpl.class)
-public class MailAccountServiceImplTest extends BaseDbUnitTest {
-
-    @Resource
-    private MailAccountServiceImpl mailAccountService;
-
-    @Resource
-    private MailAccountMapper mailAccountMapper;
-
-    @MockBean
-    private MailTemplateService mailTemplateService;
-
-    @Test
-    public void testCreateMailAccount_success() {
-        // 准备参数
-        MailAccountSaveReqVO reqVO = randomPojo(MailAccountSaveReqVO.class, o -> o.setMail(randomEmail()))
-                .setId(null); // 防止 id 被赋值
-
-        // 调用
-        Long mailAccountId = mailAccountService.createMailAccount(reqVO);
-        // 断言
-        assertNotNull(mailAccountId);
-        // 校验记录的属性是否正确
-        MailAccountDO mailAccount = mailAccountMapper.selectById(mailAccountId);
-        assertPojoEquals(reqVO, mailAccount, "id");
-    }
-
-    @Test
-    public void testUpdateMailAccount_success() {
-        // mock 数据
-        MailAccountDO dbMailAccount = randomPojo(MailAccountDO.class);
-        mailAccountMapper.insert(dbMailAccount);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        MailAccountSaveReqVO reqVO = randomPojo(MailAccountSaveReqVO.class, o -> {
-            o.setId(dbMailAccount.getId()); // 设置更新的 ID
-            o.setMail(randomEmail());
-        });
-
-        // 调用
-        mailAccountService.updateMailAccount(reqVO);
-        // 校验是否更新正确
-        MailAccountDO mailAccount = mailAccountMapper.selectById(reqVO.getId()); // 获取最新的
-        assertPojoEquals(reqVO, mailAccount);
-    }
-
-    @Test
-    public void testUpdateMailAccount_notExists() {
-        // 准备参数
-        MailAccountSaveReqVO reqVO = randomPojo(MailAccountSaveReqVO.class);
-
-        // 调用, 并断言异常
-        assertServiceException(() -> mailAccountService.updateMailAccount(reqVO), MAIL_ACCOUNT_NOT_EXISTS);
-    }
-
-    @Test
-    public void testDeleteMailAccount_success() {
-        // mock 数据
-        MailAccountDO dbMailAccount = randomPojo(MailAccountDO.class);
-        mailAccountMapper.insert(dbMailAccount);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        Long id = dbMailAccount.getId();
-        // mock 方法(无关联模版)
-        when(mailTemplateService.getMailTemplateCountByAccountId(eq(id))).thenReturn(0L);
-
-        // 调用
-        mailAccountService.deleteMailAccount(id);
-        // 校验数据不存在了
-        assertNull(mailAccountMapper.selectById(id));
-    }
-
-    @Test
-    public void testGetMailAccountFromCache() {
-        // mock 数据
-        MailAccountDO dbMailAccount = randomPojo(MailAccountDO.class);
-        mailAccountMapper.insert(dbMailAccount);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        Long id = dbMailAccount.getId();
-
-        // 调用
-        MailAccountDO mailAccount = mailAccountService.getMailAccountFromCache(id);
-        // 断言
-        assertPojoEquals(dbMailAccount, mailAccount);
-    }
-
-    @Test
-    public void testDeleteMailAccount_notExists() {
-        // 准备参数
-        Long id = randomLongId();
-
-        // 调用, 并断言异常
-        assertServiceException(() -> mailAccountService.deleteMailAccount(id), MAIL_ACCOUNT_NOT_EXISTS);
-    }
-
-    @Test
-    public void testGetMailAccountPage() {
-        // mock 数据
-        MailAccountDO dbMailAccount = randomPojo(MailAccountDO.class, o -> { // 等会查询到
-            o.setMail("768@qq.com");
-            o.setUsername("yunai");
-        });
-        mailAccountMapper.insert(dbMailAccount);
-        // 测试 mail 不匹配
-        mailAccountMapper.insert(cloneIgnoreId(dbMailAccount, o -> o.setMail("788@qq.com")));
-        // 测试 username 不匹配
-        mailAccountMapper.insert(cloneIgnoreId(dbMailAccount, o -> o.setUsername("tudou")));
-        // 准备参数
-        MailAccountPageReqVO reqVO = new MailAccountPageReqVO();
-        reqVO.setMail("768");
-        reqVO.setUsername("yu");
-
-        // 调用
-        PageResult<MailAccountDO> pageResult = mailAccountService.getMailAccountPage(reqVO);
-        // 断言
-        assertEquals(1, pageResult.getTotal());
-        assertEquals(1, pageResult.getList().size());
-        assertPojoEquals(dbMailAccount, pageResult.getList().get(0));
-    }
-
-    @Test
-    public void testGetMailAccount() {
-        // mock 数据
-        MailAccountDO dbMailAccount = randomPojo(MailAccountDO.class);
-        mailAccountMapper.insert(dbMailAccount);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        Long id = dbMailAccount.getId();
-
-        // 调用
-        MailAccountDO mailAccount = mailAccountService.getMailAccount(id);
-        // 断言
-        assertPojoEquals(dbMailAccount, mailAccount);
-    }
-
-    @Test
-    public void testGetMailAccountList() {
-        // mock 数据
-        MailAccountDO dbMailAccount01 = randomPojo(MailAccountDO.class);
-        mailAccountMapper.insert(dbMailAccount01);
-        MailAccountDO dbMailAccount02 = randomPojo(MailAccountDO.class);
-        mailAccountMapper.insert(dbMailAccount02);
-        // 准备参数
-
-        // 调用
-        List<MailAccountDO> list = mailAccountService.getMailAccountList();
-        // 断言
-        assertEquals(2, list.size());
-        assertPojoEquals(dbMailAccount01, list.get(0));
-        assertPojoEquals(dbMailAccount02, list.get(1));
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/mail/MailLogServiceImplTest.java b/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/mail/MailLogServiceImplTest.java
deleted file mode 100644
index fc7f64e..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/mail/MailLogServiceImplTest.java
+++ /dev/null
@@ -1,183 +0,0 @@
-package com.iailab.module.system.service.mail;
-
-import cn.hutool.core.map.MapUtil;
-import com.iailab.framework.common.enums.UserTypeEnum;
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.framework.test.core.ut.BaseDbUnitTest;
-import com.iailab.module.system.controller.admin.mail.vo.log.MailLogPageReqVO;
-import com.iailab.module.system.dal.dataobject.mail.MailAccountDO;
-import com.iailab.module.system.dal.dataobject.mail.MailLogDO;
-import com.iailab.module.system.dal.dataobject.mail.MailTemplateDO;
-import com.iailab.module.system.dal.mysql.mail.MailLogMapper;
-import com.iailab.module.system.enums.mail.MailSendStatusEnum;
-import org.junit.jupiter.api.Test;
-import org.springframework.context.annotation.Import;
-
-import javax.annotation.Resource;
-import java.util.Map;
-
-import static cn.hutool.core.util.RandomUtil.randomEle;
-import static com.iailab.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
-import static com.iailab.framework.common.util.date.LocalDateTimeUtils.buildTime;
-import static com.iailab.framework.common.util.object.ObjectUtils.cloneIgnoreId;
-import static com.iailab.framework.test.core.util.AssertUtils.assertPojoEquals;
-import static com.iailab.framework.test.core.util.RandomUtils.*;
-import static org.junit.jupiter.api.Assertions.*;
-
-/**
- * {@link MailLogServiceImpl} 的单元测试类
- *
- * @author iailab
- */
-@Import(MailLogServiceImpl.class)
-public class MailLogServiceImplTest extends BaseDbUnitTest {
-
-    @Resource
-    private MailLogServiceImpl mailLogService;
-
-    @Resource
-    private MailLogMapper mailLogMapper;
-
-    @Test
-    public void testCreateMailLog() {
-        // 准备参数
-        Long userId = randomLongId();
-        Integer userType = randomEle(UserTypeEnum.values()).getValue();
-        String toMail = randomEmail();
-        MailAccountDO account = randomPojo(MailAccountDO.class);
-        MailTemplateDO template = randomPojo(MailTemplateDO.class);
-        String templateContent = randomString();
-        Map<String, Object> templateParams = randomTemplateParams();
-        Boolean isSend = true;
-        // mock 方法
-
-        // 调用
-        Long logId = mailLogService.createMailLog(userId, userType, toMail, account, template, templateContent, templateParams, isSend);
-        // 断言
-        MailLogDO log = mailLogMapper.selectById(logId);
-        assertNotNull(log);
-        assertEquals(MailSendStatusEnum.INIT.getStatus(), log.getSendStatus());
-        assertEquals(userId, log.getUserId());
-        assertEquals(userType, log.getUserType());
-        assertEquals(toMail, log.getToMail());
-        assertEquals(account.getId(), log.getAccountId());
-        assertEquals(account.getMail(), log.getFromMail());
-        assertEquals(template.getId(), log.getTemplateId());
-        assertEquals(template.getCode(), log.getTemplateCode());
-        assertEquals(template.getNickname(), log.getTemplateNickname());
-        assertEquals(template.getTitle(), log.getTemplateTitle());
-        assertEquals(templateContent, log.getTemplateContent());
-        assertEquals(templateParams, log.getTemplateParams());
-    }
-
-    @Test
-    public void testUpdateMailSendResult_success() {
-        // mock 数据
-        MailLogDO log = randomPojo(MailLogDO.class, o -> {
-            o.setSendStatus(MailSendStatusEnum.INIT.getStatus());
-            o.setSendTime(null).setSendMessageId(null).setSendException(null)
-                    .setTemplateParams(randomTemplateParams());
-        });
-        mailLogMapper.insert(log);
-        // 准备参数
-        Long logId = log.getId();
-        String messageId = randomString();
-
-        // 调用
-        mailLogService.updateMailSendResult(logId, messageId, null);
-        // 断言
-        MailLogDO dbLog = mailLogMapper.selectById(logId);
-        assertEquals(MailSendStatusEnum.SUCCESS.getStatus(), dbLog.getSendStatus());
-        assertNotNull(dbLog.getSendTime());
-        assertEquals(messageId, dbLog.getSendMessageId());
-        assertNull(dbLog.getSendException());
-    }
-
-    @Test
-    public void testUpdateMailSendResult_exception() {
-        // mock 数据
-        MailLogDO log = randomPojo(MailLogDO.class, o -> {
-            o.setSendStatus(MailSendStatusEnum.INIT.getStatus());
-            o.setSendTime(null).setSendMessageId(null).setSendException(null)
-                    .setTemplateParams(randomTemplateParams());
-        });
-        mailLogMapper.insert(log);
-        // 准备参数
-        Long logId = log.getId();
-        Exception exception = new NullPointerException("测试异常");
-
-        // 调用
-        mailLogService.updateMailSendResult(logId, null, exception);
-        // 断言
-        MailLogDO dbLog = mailLogMapper.selectById(logId);
-        assertEquals(MailSendStatusEnum.FAILURE.getStatus(), dbLog.getSendStatus());
-        assertNotNull(dbLog.getSendTime());
-        assertNull(dbLog.getSendMessageId());
-        assertEquals("NullPointerException: 测试异常", dbLog.getSendException());
-    }
-
-    @Test
-    public void testGetMailLog() {
-        // mock 数据
-        MailLogDO dbMailLog = randomPojo(MailLogDO.class, o -> o.setTemplateParams(randomTemplateParams()));
-        mailLogMapper.insert(dbMailLog);
-        // 准备参数
-        Long id = dbMailLog.getId();
-
-        // 调用
-        MailLogDO mailLog = mailLogService.getMailLog(id);
-        // 断言
-        assertPojoEquals(dbMailLog, mailLog);
-    }
-
-    @Test
-    public void testGetMailLogPage() {
-       // mock 数据
-       MailLogDO dbMailLog = randomPojo(MailLogDO.class, o -> { // 等会查询到
-           o.setUserId(1L);
-           o.setUserType(UserTypeEnum.ADMIN.getValue());
-           o.setToMail("768@qq.com");
-           o.setAccountId(10L);
-           o.setTemplateId(100L);
-           o.setSendStatus(MailSendStatusEnum.INIT.getStatus());
-           o.setSendTime(buildTime(2023, 2, 10));
-           o.setTemplateParams(randomTemplateParams());
-       });
-       mailLogMapper.insert(dbMailLog);
-       // 测试 userId 不匹配
-       mailLogMapper.insert(cloneIgnoreId(dbMailLog, o -> o.setUserId(2L)));
-       // 测试 userType 不匹配
-       mailLogMapper.insert(cloneIgnoreId(dbMailLog, o -> o.setUserType(UserTypeEnum.MEMBER.getValue())));
-       // 测试 toMail 不匹配
-       mailLogMapper.insert(cloneIgnoreId(dbMailLog, o -> o.setToMail("788@.qq.com")));
-       // 测试 accountId 不匹配
-       mailLogMapper.insert(cloneIgnoreId(dbMailLog, o -> o.setAccountId(11L)));
-       // 测试 templateId 不匹配
-       mailLogMapper.insert(cloneIgnoreId(dbMailLog, o -> o.setTemplateId(101L)));
-       // 测试 sendStatus 不匹配
-       mailLogMapper.insert(cloneIgnoreId(dbMailLog, o -> o.setSendStatus(MailSendStatusEnum.SUCCESS.getStatus())));
-       // 测试 sendTime 不匹配
-       mailLogMapper.insert(cloneIgnoreId(dbMailLog, o -> o.setSendTime(buildTime(2023, 3, 10))));
-       // 准备参数
-       MailLogPageReqVO reqVO = new MailLogPageReqVO();
-       reqVO.setUserId(1L);
-       reqVO.setUserType(UserTypeEnum.ADMIN.getValue());
-       reqVO.setToMail("768");
-       reqVO.setAccountId(10L);
-       reqVO.setTemplateId(100L);
-       reqVO.setSendStatus(MailSendStatusEnum.INIT.getStatus());
-       reqVO.setSendTime((buildBetweenTime(2023, 2, 1, 2023, 2, 15)));
-
-       // 调用
-       PageResult<MailLogDO> pageResult = mailLogService.getMailLogPage(reqVO);
-       // 断言
-       assertEquals(1, pageResult.getTotal());
-       assertEquals(1, pageResult.getList().size());
-       assertPojoEquals(dbMailLog, pageResult.getList().get(0));
-    }
-
-    private static Map<String, Object> randomTemplateParams() {
-        return MapUtil.<String, Object>builder().put(randomString(), randomString())
-                .put(randomString(), randomString()).build();
-    }
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/mail/MailSendServiceImplTest.java b/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/mail/MailSendServiceImplTest.java
deleted file mode 100644
index 5492376..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/mail/MailSendServiceImplTest.java
+++ /dev/null
@@ -1,332 +0,0 @@
-package com.iailab.module.system.service.mail;
-
-import cn.hutool.core.map.MapUtil;
-import cn.hutool.extra.mail.MailAccount;
-import cn.hutool.extra.mail.MailUtil;
-import com.iailab.framework.common.enums.CommonStatusEnum;
-import com.iailab.framework.common.enums.UserTypeEnum;
-import com.iailab.framework.test.core.ut.BaseMockitoUnitTest;
-import com.iailab.framework.test.core.util.RandomUtils;
-import com.iailab.module.system.dal.dataobject.mail.MailAccountDO;
-import com.iailab.module.system.dal.dataobject.mail.MailTemplateDO;
-import com.iailab.module.system.dal.dataobject.user.AdminUserDO;
-import com.iailab.module.system.mq.message.mail.MailSendMessage;
-import com.iailab.module.system.mq.producer.mail.MailProducer;
-import com.iailab.module.system.service.member.MemberService;
-import com.iailab.module.system.service.user.AdminUserService;
-import org.assertj.core.util.Lists;
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.Test;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.MockedStatic;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import static cn.hutool.core.util.RandomUtil.randomEle;
-import static com.iailab.framework.test.core.util.AssertUtils.assertServiceException;
-import static com.iailab.framework.test.core.util.RandomUtils.*;
-import static com.iailab.module.system.enums.ErrorCodeConstants.*;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.*;
-
-public class MailSendServiceImplTest extends BaseMockitoUnitTest {
-
-    @InjectMocks
-    private MailSendServiceImpl mailSendService;
-
-    @Mock
-    private AdminUserService adminUserService;
-    @Mock
-    private MemberService memberService;
-    @Mock
-    private MailAccountService mailAccountService;
-    @Mock
-    private MailTemplateService mailTemplateService;
-    @Mock
-    private MailLogService mailLogService;
-    @Mock
-    private MailProducer mailProducer;
-
-    /**
-     * 用于快速测试你的邮箱账号是否正常
-     */
-    @Test
-    @Disabled
-    public void testDemo() {
-        MailAccount mailAccount = new MailAccount()
-//                .setFrom("奥特曼 <ydym_test@163.com>")
-                .setFrom("ydym_test@163.com") // 邮箱地址
-                .setHost("smtp.163.com").setPort(465).setSslEnable(true) // SMTP 服务器
-                .setAuth(true).setUser("ydym_test@163.com").setPass("WBZTEINMIFVRYSOE"); // 登录账号密码
-        String messageId = MailUtil.send(mailAccount, "7685413@qq.com", "主题", "内容", false);
-        System.out.println("发送结果:" + messageId);
-    }
-
-    @Test
-    public void testSendSingleMailToAdmin() {
-        // 准备参数
-        Long userId = randomLongId();
-        String templateCode = RandomUtils.randomString();
-        Map<String, Object> templateParams = MapUtil.<String, Object>builder().put("code", "1234")
-                .put("op", "login").build();
-        // mock adminUserService 的方法
-        AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setMobile("15601691300"));
-        when(adminUserService.getUser(eq(userId))).thenReturn(user);
-
-        // mock MailTemplateService 的方法
-        MailTemplateDO template = randomPojo(MailTemplateDO.class, o -> {
-            o.setStatus(CommonStatusEnum.ENABLE.getStatus());
-            o.setContent("验证码为{code}, 操作为{op}");
-            o.setParams(Lists.newArrayList("code", "op"));
-        });
-        when(mailTemplateService.getMailTemplateByCodeFromCache(eq(templateCode))).thenReturn(template);
-        String title = RandomUtils.randomString();
-        when(mailTemplateService.formatMailTemplateContent(eq(template.getTitle()), eq(templateParams)))
-                .thenReturn(title);
-        String content = RandomUtils.randomString();
-        when(mailTemplateService.formatMailTemplateContent(eq(template.getContent()), eq(templateParams)))
-                .thenReturn(content);
-        // mock MailAccountService 的方法
-        MailAccountDO account = randomPojo(MailAccountDO.class);
-        when(mailAccountService.getMailAccountFromCache(eq(template.getAccountId()))).thenReturn(account);
-        // mock MailLogService 的方法
-        Long mailLogId = randomLongId();
-        when(mailLogService.createMailLog(eq(userId), eq(UserTypeEnum.ADMIN.getValue()), eq(user.getEmail()),
-                eq(account), eq(template), eq(content), eq(templateParams), eq(true))).thenReturn(mailLogId);
-
-        // 调用
-        Long resultMailLogId = mailSendService.sendSingleMailToAdmin(null, userId, templateCode, templateParams);
-        // 断言
-        assertEquals(mailLogId, resultMailLogId);
-        // 断言调用
-        verify(mailProducer).sendMailSendMessage(eq(mailLogId), eq(user.getEmail()),
-                eq(account.getId()), eq(template.getNickname()), eq(title), eq(content));
-    }
-
-    @Test
-    public void testSendSingleMailToMember() {
-        // 准备参数
-        Long userId = randomLongId();
-        String templateCode = RandomUtils.randomString();
-        Map<String, Object> templateParams = MapUtil.<String, Object>builder().put("code", "1234")
-                .put("op", "login").build();
-        // mock memberService 的方法
-        String mail = randomEmail();
-        when(memberService.getMemberUserEmail(eq(userId))).thenReturn(mail);
-
-        // mock MailTemplateService 的方法
-        MailTemplateDO template = randomPojo(MailTemplateDO.class, o -> {
-            o.setStatus(CommonStatusEnum.ENABLE.getStatus());
-            o.setContent("验证码为{code}, 操作为{op}");
-            o.setParams(Lists.newArrayList("code", "op"));
-        });
-        when(mailTemplateService.getMailTemplateByCodeFromCache(eq(templateCode))).thenReturn(template);
-        String title = RandomUtils.randomString();
-        when(mailTemplateService.formatMailTemplateContent(eq(template.getTitle()), eq(templateParams)))
-                .thenReturn(title);
-        String content = RandomUtils.randomString();
-        when(mailTemplateService.formatMailTemplateContent(eq(template.getContent()), eq(templateParams)))
-                .thenReturn(content);
-        // mock MailAccountService 的方法
-        MailAccountDO account = randomPojo(MailAccountDO.class);
-        when(mailAccountService.getMailAccountFromCache(eq(template.getAccountId()))).thenReturn(account);
-        // mock MailLogService 的方法
-        Long mailLogId = randomLongId();
-        when(mailLogService.createMailLog(eq(userId), eq(UserTypeEnum.MEMBER.getValue()), eq(mail),
-                eq(account), eq(template), eq(content), eq(templateParams), eq(true))).thenReturn(mailLogId);
-
-        // 调用
-        Long resultMailLogId = mailSendService.sendSingleMailToMember(null, userId, templateCode, templateParams);
-        // 断言
-        assertEquals(mailLogId, resultMailLogId);
-        // 断言调用
-        verify(mailProducer).sendMailSendMessage(eq(mailLogId), eq(mail),
-                eq(account.getId()), eq(template.getNickname()), eq(title), eq(content));
-    }
-
-    /**
-     * 发送成功,当短信模板开启时
-     */
-    @Test
-    public void testSendSingleMail_successWhenMailTemplateEnable() {
-        // 准备参数
-        String mail = randomEmail();
-        Long userId = randomLongId();
-        Integer userType = randomEle(UserTypeEnum.values()).getValue();
-        String templateCode = RandomUtils.randomString();
-        Map<String, Object> templateParams = MapUtil.<String, Object>builder().put("code", "1234")
-                .put("op", "login").build();
-        // mock MailTemplateService 的方法
-        MailTemplateDO template = randomPojo(MailTemplateDO.class, o -> {
-            o.setStatus(CommonStatusEnum.ENABLE.getStatus());
-            o.setContent("验证码为{code}, 操作为{op}");
-            o.setParams(Lists.newArrayList("code", "op"));
-        });
-        when(mailTemplateService.getMailTemplateByCodeFromCache(eq(templateCode))).thenReturn(template);
-        String title = RandomUtils.randomString();
-        when(mailTemplateService.formatMailTemplateContent(eq(template.getTitle()), eq(templateParams)))
-                .thenReturn(title);
-        String content = RandomUtils.randomString();
-        when(mailTemplateService.formatMailTemplateContent(eq(template.getContent()), eq(templateParams)))
-                .thenReturn(content);
-        // mock MailAccountService 的方法
-        MailAccountDO account = randomPojo(MailAccountDO.class);
-        when(mailAccountService.getMailAccountFromCache(eq(template.getAccountId()))).thenReturn(account);
-        // mock MailLogService 的方法
-        Long mailLogId = randomLongId();
-        when(mailLogService.createMailLog(eq(userId), eq(userType), eq(mail),
-                eq(account), eq(template), eq(content), eq(templateParams), eq(true))).thenReturn(mailLogId);
-
-        // 调用
-        Long resultMailLogId = mailSendService.sendSingleMail(mail, userId, userType, templateCode, templateParams);
-        // 断言
-        assertEquals(mailLogId, resultMailLogId);
-        // 断言调用
-        verify(mailProducer).sendMailSendMessage(eq(mailLogId), eq(mail),
-                eq(account.getId()), eq(template.getNickname()), eq(title), eq(content));
-    }
-
-    /**
-     * 发送成功,当短信模板关闭时
-     */
-    @Test
-    public void testSendSingleMail_successWhenSmsTemplateDisable() {
-        // 准备参数
-        String mail = randomEmail();
-        Long userId = randomLongId();
-        Integer userType = randomEle(UserTypeEnum.values()).getValue();
-        String templateCode = RandomUtils.randomString();
-        Map<String, Object> templateParams = MapUtil.<String, Object>builder().put("code", "1234")
-                .put("op", "login").build();
-        // mock MailTemplateService 的方法
-        MailTemplateDO template = randomPojo(MailTemplateDO.class, o -> {
-            o.setStatus(CommonStatusEnum.DISABLE.getStatus());
-            o.setContent("验证码为{code}, 操作为{op}");
-            o.setParams(Lists.newArrayList("code", "op"));
-        });
-        when(mailTemplateService.getMailTemplateByCodeFromCache(eq(templateCode))).thenReturn(template);
-        String title = RandomUtils.randomString();
-        when(mailTemplateService.formatMailTemplateContent(eq(template.getTitle()), eq(templateParams)))
-                .thenReturn(title);
-        String content = RandomUtils.randomString();
-        when(mailTemplateService.formatMailTemplateContent(eq(template.getContent()), eq(templateParams)))
-                .thenReturn(content);
-        // mock MailAccountService 的方法
-        MailAccountDO account = randomPojo(MailAccountDO.class);
-        when(mailAccountService.getMailAccountFromCache(eq(template.getAccountId()))).thenReturn(account);
-        // mock MailLogService 的方法
-        Long mailLogId = randomLongId();
-        when(mailLogService.createMailLog(eq(userId), eq(userType), eq(mail),
-                eq(account), eq(template), eq(content), eq(templateParams), eq(false))).thenReturn(mailLogId);
-
-        // 调用
-        Long resultMailLogId = mailSendService.sendSingleMail(mail, userId, userType, templateCode, templateParams);
-        // 断言
-        assertEquals(mailLogId, resultMailLogId);
-        // 断言调用
-        verify(mailProducer, times(0)).sendMailSendMessage(anyLong(), anyString(),
-                anyLong(), anyString(), anyString(), anyString());
-    }
-
-    @Test
-    public void testValidateMailTemplateValid_notExists() {
-        // 准备参数
-        String templateCode = RandomUtils.randomString();
-        // mock 方法
-
-        // 调用,并断言异常
-        assertServiceException(() -> mailSendService.validateMailTemplate(templateCode),
-                MAIL_TEMPLATE_NOT_EXISTS);
-    }
-
-    @Test
-    public void testValidateTemplateParams_paramMiss() {
-        // 准备参数
-        MailTemplateDO template = randomPojo(MailTemplateDO.class,
-                o -> o.setParams(Lists.newArrayList("code")));
-        Map<String, Object> templateParams = new HashMap<>();
-        // mock 方法
-
-        // 调用,并断言异常
-        assertServiceException(() -> mailSendService.validateTemplateParams(template, templateParams),
-                MAIL_SEND_TEMPLATE_PARAM_MISS, "code");
-    }
-
-    @Test
-    public void testValidateMail_notExists() {
-        // 准备参数
-        // mock 方法
-
-        // 调用,并断言异常
-        assertServiceException(() -> mailSendService.validateMail(null),
-                MAIL_SEND_MAIL_NOT_EXISTS);
-    }
-
-    @Test
-    public void testDoSendMail_success() {
-        try (MockedStatic<MailUtil> mailUtilMock = mockStatic(MailUtil.class)) {
-            // 准备参数
-            MailSendMessage message = randomPojo(MailSendMessage.class, o -> o.setNickname("iailab"));
-            // mock 方法(获得邮箱账号)
-            MailAccountDO account = randomPojo(MailAccountDO.class, o -> o.setMail("7685@qq.com"));
-            when(mailAccountService.getMailAccountFromCache(eq(message.getAccountId())))
-                    .thenReturn(account);
-
-            // mock 方法(发送邮件)
-            String messageId = randomString();
-            mailUtilMock.when(() -> MailUtil.send(
-                    argThat(mailAccount -> {
-                        assertEquals("iailab <7685@qq.com>", mailAccount.getFrom());
-                        assertTrue(mailAccount.isAuth());
-                        assertEquals(account.getUsername(), mailAccount.getUser());
-                        assertEquals(account.getPassword(), mailAccount.getPass());
-                        assertEquals(account.getHost(), mailAccount.getHost());
-                        assertEquals(account.getPort(), mailAccount.getPort());
-                        assertEquals(account.getSslEnable(), mailAccount.isSslEnable());
-                        return true;
-                    }), eq(message.getMail()), eq(message.getTitle()), eq(message.getContent()), eq(true)))
-                    .thenReturn(messageId);
-
-            // 调用
-            mailSendService.doSendMail(message);
-            // 断言
-            verify(mailLogService).updateMailSendResult(eq(message.getLogId()), eq(messageId), isNull());
-        }
-    }
-
-    @Test
-    public void testDoSendMail_exception() {
-        try (MockedStatic<MailUtil> mailUtilMock = mockStatic(MailUtil.class)) {
-            // 准备参数
-            MailSendMessage message = randomPojo(MailSendMessage.class, o -> o.setNickname("iailab"));
-            // mock 方法(获得邮箱账号)
-            MailAccountDO account = randomPojo(MailAccountDO.class, o -> o.setMail("7685@qq.com"));
-            when(mailAccountService.getMailAccountFromCache(eq(message.getAccountId())))
-                    .thenReturn(account);
-
-            // mock 方法(发送邮件)
-            Exception e = new NullPointerException("啦啦啦");
-            mailUtilMock.when(() -> MailUtil.send(argThat(mailAccount -> {
-                        assertEquals("iailab <7685@qq.com>", mailAccount.getFrom());
-                        assertTrue(mailAccount.isAuth());
-                        assertEquals(account.getUsername(), mailAccount.getUser());
-                        assertEquals(account.getPassword(), mailAccount.getPass());
-                        assertEquals(account.getHost(), mailAccount.getHost());
-                        assertEquals(account.getPort(), mailAccount.getPort());
-                        assertEquals(account.getSslEnable(), mailAccount.isSslEnable());
-                        return true;
-                    }), eq(message.getMail()), eq(message.getTitle()), eq(message.getContent()), eq(true)))
-                    .thenThrow(e);
-
-            // 调用
-            mailSendService.doSendMail(message);
-            // 断言
-            verify(mailLogService).updateMailSendResult(eq(message.getLogId()), isNull(), same(e));
-        }
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/mail/MailTemplateServiceImplTest.java b/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/mail/MailTemplateServiceImplTest.java
deleted file mode 100644
index b5bf240..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/mail/MailTemplateServiceImplTest.java
+++ /dev/null
@@ -1,215 +0,0 @@
-package com.iailab.module.system.service.mail;
-
-import com.iailab.framework.common.enums.CommonStatusEnum;
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.framework.test.core.ut.BaseDbUnitTest;
-import com.iailab.module.system.controller.admin.mail.vo.template.MailTemplatePageReqVO;
-import com.iailab.module.system.controller.admin.mail.vo.template.MailTemplateSaveReqVO;
-import com.iailab.module.system.dal.dataobject.mail.MailTemplateDO;
-import com.iailab.module.system.dal.mysql.mail.MailTemplateMapper;
-import org.junit.jupiter.api.Test;
-import org.springframework.context.annotation.Import;
-
-import javax.annotation.Resource;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import static com.iailab.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
-import static com.iailab.framework.common.util.date.LocalDateTimeUtils.buildTime;
-import static com.iailab.framework.common.util.object.ObjectUtils.cloneIgnoreId;
-import static com.iailab.framework.test.core.util.AssertUtils.assertPojoEquals;
-import static com.iailab.framework.test.core.util.AssertUtils.assertServiceException;
-import static com.iailab.framework.test.core.util.RandomUtils.randomLongId;
-import static com.iailab.framework.test.core.util.RandomUtils.randomPojo;
-import static com.iailab.module.system.enums.ErrorCodeConstants.MAIL_TEMPLATE_NOT_EXISTS;
-import static org.junit.jupiter.api.Assertions.*;
-
-/**
- * {@link MailTemplateServiceImpl} 的单元测试类
- *
- * @author iailab
- */
-@Import(MailTemplateServiceImpl.class)
-public class MailTemplateServiceImplTest extends BaseDbUnitTest {
-
-    @Resource
-    private MailTemplateServiceImpl mailTemplateService;
-
-    @Resource
-    private MailTemplateMapper mailTemplateMapper;
-
-    @Test
-    public void testCreateMailTemplate_success() {
-        // 准备参数
-        MailTemplateSaveReqVO reqVO = randomPojo(MailTemplateSaveReqVO.class)
-                .setId(null); // 防止 id 被赋值
-
-        // 调用
-        Long mailTemplateId = mailTemplateService.createMailTemplate(reqVO);
-        // 断言
-        assertNotNull(mailTemplateId);
-        // 校验记录的属性是否正确
-        MailTemplateDO mailTemplate = mailTemplateMapper.selectById(mailTemplateId);
-        assertPojoEquals(reqVO, mailTemplate, "id");
-    }
-
-    @Test
-    public void testUpdateMailTemplate_success() {
-        // mock 数据
-        MailTemplateDO dbMailTemplate = randomPojo(MailTemplateDO.class);
-        mailTemplateMapper.insert(dbMailTemplate);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        MailTemplateSaveReqVO reqVO = randomPojo(MailTemplateSaveReqVO.class, o -> {
-            o.setId(dbMailTemplate.getId()); // 设置更新的 ID
-        });
-
-        // 调用
-        mailTemplateService.updateMailTemplate(reqVO);
-        // 校验是否更新正确
-        MailTemplateDO mailTemplate = mailTemplateMapper.selectById(reqVO.getId()); // 获取最新的
-        assertPojoEquals(reqVO, mailTemplate);
-    }
-
-    @Test
-    public void testUpdateMailTemplate_notExists() {
-        // 准备参数
-        MailTemplateSaveReqVO reqVO = randomPojo(MailTemplateSaveReqVO.class);
-
-        // 调用, 并断言异常
-        assertServiceException(() -> mailTemplateService.updateMailTemplate(reqVO), MAIL_TEMPLATE_NOT_EXISTS);
-    }
-
-    @Test
-    public void testDeleteMailTemplate_success() {
-        // mock 数据
-        MailTemplateDO dbMailTemplate = randomPojo(MailTemplateDO.class);
-        mailTemplateMapper.insert(dbMailTemplate);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        Long id = dbMailTemplate.getId();
-
-        // 调用
-        mailTemplateService.deleteMailTemplate(id);
-        // 校验数据不存在了
-        assertNull(mailTemplateMapper.selectById(id));
-    }
-
-    @Test
-    public void testDeleteMailTemplate_notExists() {
-        // 准备参数
-        Long id = randomLongId();
-
-        // 调用, 并断言异常
-        assertServiceException(() -> mailTemplateService.deleteMailTemplate(id), MAIL_TEMPLATE_NOT_EXISTS);
-    }
-
-    @Test
-    public void testGetMailTemplatePage() {
-        // mock 数据
-        MailTemplateDO dbMailTemplate = randomPojo(MailTemplateDO.class, o -> { // 等会查询到
-            o.setName("源码");
-            o.setCode("test_01");
-            o.setAccountId(1L);
-            o.setStatus(CommonStatusEnum.ENABLE.getStatus());
-            o.setCreateTime(buildTime(2023, 2, 3));
-        });
-        mailTemplateMapper.insert(dbMailTemplate);
-        // 测试 name 不匹配
-        mailTemplateMapper.insert(cloneIgnoreId(dbMailTemplate, o -> o.setName("平台")));
-        // 测试 code 不匹配
-        mailTemplateMapper.insert(cloneIgnoreId(dbMailTemplate, o -> o.setCode("test_02")));
-        // 测试 accountId 不匹配
-        mailTemplateMapper.insert(cloneIgnoreId(dbMailTemplate, o -> o.setAccountId(2L)));
-        // 测试 status 不匹配
-        mailTemplateMapper.insert(cloneIgnoreId(dbMailTemplate, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
-        // 测试 createTime 不匹配
-        mailTemplateMapper.insert(cloneIgnoreId(dbMailTemplate, o -> o.setCreateTime(buildTime(2023, 1, 5))));
-        // 准备参数
-        MailTemplatePageReqVO reqVO = new MailTemplatePageReqVO();
-        reqVO.setName("源");
-        reqVO.setCode("est_01");
-        reqVO.setAccountId(1L);
-        reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
-        reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 5));
-
-        // 调用
-        PageResult<MailTemplateDO> pageResult = mailTemplateService.getMailTemplatePage(reqVO);
-        // 断言
-        assertEquals(1, pageResult.getTotal());
-        assertEquals(1, pageResult.getList().size());
-        assertPojoEquals(dbMailTemplate, pageResult.getList().get(0));
-    }
-
-    @Test
-    public void testGetMailTemplateList() {
-        // mock 数据
-        MailTemplateDO dbMailTemplate01 = randomPojo(MailTemplateDO.class);
-        mailTemplateMapper.insert(dbMailTemplate01);
-        MailTemplateDO dbMailTemplate02 = randomPojo(MailTemplateDO.class);
-        mailTemplateMapper.insert(dbMailTemplate02);
-
-        // 调用
-        List<MailTemplateDO> list = mailTemplateService.getMailTemplateList();
-        // 断言
-        assertEquals(2, list.size());
-        assertEquals(dbMailTemplate01, list.get(0));
-        assertEquals(dbMailTemplate02, list.get(1));
-    }
-
-    @Test
-    public void testGetMailTemplate() {
-        // mock 数据
-        MailTemplateDO dbMailTemplate = randomPojo(MailTemplateDO.class);
-        mailTemplateMapper.insert(dbMailTemplate);
-        // 准备参数
-        Long id = dbMailTemplate.getId();
-
-        // 调用
-        MailTemplateDO mailTemplate = mailTemplateService.getMailTemplate(id);
-        // 断言
-        assertPojoEquals(dbMailTemplate, mailTemplate);
-    }
-
-    @Test
-    public void testGetMailTemplateByCodeFromCache() {
-        // mock 数据
-        MailTemplateDO dbMailTemplate = randomPojo(MailTemplateDO.class);
-        mailTemplateMapper.insert(dbMailTemplate);
-        // 准备参数
-        String code = dbMailTemplate.getCode();
-
-        // 调用
-        MailTemplateDO mailTemplate = mailTemplateService.getMailTemplateByCodeFromCache(code);
-        // 断言
-        assertPojoEquals(dbMailTemplate, mailTemplate);
-    }
-
-    @Test
-    public void testFormatMailTemplateContent() {
-        // 准备参数
-        Map<String, Object> params = new HashMap<>();
-        params.put("name", "小红");
-        params.put("what", "饭");
-
-        // 调用,并断言
-        assertEquals("小红,你好,饭吃了吗?",
-                mailTemplateService.formatMailTemplateContent("{name},你好,{what}吃了吗?", params));
-    }
-
-    @Test
-    public void testCountByAccountId() {
-        // mock 数据
-        MailTemplateDO dbMailTemplate = randomPojo(MailTemplateDO.class);
-        mailTemplateMapper.insert(dbMailTemplate);
-        // 测试 accountId 不匹配
-        mailTemplateMapper.insert(cloneIgnoreId(dbMailTemplate, o -> o.setAccountId(2L)));
-        // 准备参数
-        Long accountId = dbMailTemplate.getAccountId();
-
-        // 调用
-        long count = mailTemplateService.getMailTemplateCountByAccountId(accountId);
-        // 断言
-        assertEquals(1, count);
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/notice/NoticeServiceImplTest.java b/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/notice/NoticeServiceImplTest.java
deleted file mode 100644
index 867cde9..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/notice/NoticeServiceImplTest.java
+++ /dev/null
@@ -1,130 +0,0 @@
-package com.iailab.module.system.service.notice;
-
-import com.iailab.framework.common.enums.CommonStatusEnum;
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.framework.test.core.ut.BaseDbUnitTest;
-import com.iailab.module.system.controller.admin.notice.vo.NoticePageReqVO;
-import com.iailab.module.system.controller.admin.notice.vo.NoticeSaveReqVO;
-import com.iailab.module.system.dal.dataobject.notice.NoticeDO;
-import com.iailab.module.system.dal.mysql.notice.NoticeMapper;
-import org.junit.jupiter.api.Test;
-import org.springframework.context.annotation.Import;
-
-import javax.annotation.Resource;
-
-import static com.iailab.framework.common.util.object.ObjectUtils.cloneIgnoreId;
-import static com.iailab.framework.test.core.util.AssertUtils.assertPojoEquals;
-import static com.iailab.framework.test.core.util.AssertUtils.assertServiceException;
-import static com.iailab.framework.test.core.util.RandomUtils.randomLongId;
-import static com.iailab.framework.test.core.util.RandomUtils.randomPojo;
-import static com.iailab.module.system.enums.ErrorCodeConstants.NOTICE_NOT_FOUND;
-import static org.junit.jupiter.api.Assertions.*;
-
-@Import(NoticeServiceImpl.class)
-class NoticeServiceImplTest extends BaseDbUnitTest {
-
-    @Resource
-    private NoticeServiceImpl noticeService;
-
-    @Resource
-    private NoticeMapper noticeMapper;
-
-    @Test
-    public void testGetNoticePage_success() {
-        // 插入前置数据
-        NoticeDO dbNotice = randomPojo(NoticeDO.class, o -> {
-            o.setTitle("尼古拉斯赵四来啦!");
-            o.setStatus(CommonStatusEnum.ENABLE.getStatus());
-        });
-        noticeMapper.insert(dbNotice);
-        // 测试 title 不匹配
-        noticeMapper.insert(cloneIgnoreId(dbNotice, o -> o.setTitle("尼古拉斯凯奇也来啦!")));
-        // 测试 status 不匹配
-        noticeMapper.insert(cloneIgnoreId(dbNotice, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
-        // 准备参数
-        NoticePageReqVO reqVO = new NoticePageReqVO();
-        reqVO.setTitle("尼古拉斯赵四来啦!");
-        reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
-
-        // 调用
-        PageResult<NoticeDO> pageResult = noticeService.getNoticePage(reqVO);
-        // 验证查询结果经过筛选
-        assertEquals(1, pageResult.getTotal());
-        assertEquals(1, pageResult.getList().size());
-        assertPojoEquals(dbNotice, pageResult.getList().get(0));
-    }
-
-    @Test
-    public void testGetNotice_success() {
-        // 插入前置数据
-        NoticeDO dbNotice = randomPojo(NoticeDO.class);
-        noticeMapper.insert(dbNotice);
-
-        // 查询
-        NoticeDO notice = noticeService.getNotice(dbNotice.getId());
-
-        // 验证插入与读取对象是否一致
-        assertNotNull(notice);
-        assertPojoEquals(dbNotice, notice);
-    }
-
-    @Test
-    public void testCreateNotice_success() {
-        // 准备参数
-        NoticeSaveReqVO reqVO = randomPojo(NoticeSaveReqVO.class)
-                .setId(null); // 避免 id 被赋值
-
-        // 调用
-        Long noticeId = noticeService.createNotice(reqVO);
-        // 校验插入属性是否正确
-        assertNotNull(noticeId);
-        NoticeDO notice = noticeMapper.selectById(noticeId);
-        assertPojoEquals(reqVO, notice, "id");
-    }
-
-    @Test
-    public void testUpdateNotice_success() {
-        // 插入前置数据
-        NoticeDO dbNoticeDO = randomPojo(NoticeDO.class);
-        noticeMapper.insert(dbNoticeDO);
-
-        // 准备更新参数
-        NoticeSaveReqVO reqVO = randomPojo(NoticeSaveReqVO.class, o -> o.setId(dbNoticeDO.getId()));
-
-        // 更新
-        noticeService.updateNotice(reqVO);
-        // 检验是否更新成功
-        NoticeDO notice = noticeMapper.selectById(reqVO.getId());
-        assertPojoEquals(reqVO, notice);
-    }
-
-    @Test
-    public void testDeleteNotice_success() {
-        // 插入前置数据
-        NoticeDO dbNotice = randomPojo(NoticeDO.class);
-        noticeMapper.insert(dbNotice);
-
-        // 删除
-        noticeService.deleteNotice(dbNotice.getId());
-
-        // 检查是否删除成功
-        assertNull(noticeMapper.selectById(dbNotice.getId()));
-    }
-
-    @Test
-    public void testValidateNoticeExists_success() {
-        // 插入前置数据
-        NoticeDO dbNotice = randomPojo(NoticeDO.class);
-        noticeMapper.insert(dbNotice);
-
-        // 成功调用
-        noticeService.validateNoticeExists(dbNotice.getId());
-    }
-
-    @Test
-    public void testValidateNoticeExists_noExists() {
-        assertServiceException(() ->
-                noticeService.validateNoticeExists(randomLongId()), NOTICE_NOT_FOUND);
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/notify/NotifyMessageServiceImplTest.java b/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/notify/NotifyMessageServiceImplTest.java
deleted file mode 100644
index cf9b8d8..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/notify/NotifyMessageServiceImplTest.java
+++ /dev/null
@@ -1,280 +0,0 @@
-package com.iailab.module.system.service.notify;
-
-import cn.hutool.core.map.MapUtil;
-import com.iailab.framework.common.enums.UserTypeEnum;
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.framework.mybatis.core.enums.SqlConstants;
-import com.iailab.framework.test.core.ut.BaseDbUnitTest;
-import com.iailab.module.system.controller.admin.notify.vo.message.NotifyMessageMyPageReqVO;
-import com.iailab.module.system.controller.admin.notify.vo.message.NotifyMessagePageReqVO;
-import com.iailab.module.system.dal.dataobject.notify.NotifyMessageDO;
-import com.iailab.module.system.dal.dataobject.notify.NotifyTemplateDO;
-import com.iailab.module.system.dal.mysql.notify.NotifyMessageMapper;
-import com.baomidou.mybatisplus.annotation.DbType;
-import org.junit.jupiter.api.Test;
-import org.springframework.context.annotation.Import;
-
-import javax.annotation.Resource;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-import static cn.hutool.core.util.RandomUtil.randomEle;
-import static com.iailab.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
-import static com.iailab.framework.common.util.date.LocalDateTimeUtils.buildTime;
-import static com.iailab.framework.common.util.object.ObjectUtils.cloneIgnoreId;
-import static com.iailab.framework.test.core.util.AssertUtils.assertPojoEquals;
-import static com.iailab.framework.test.core.util.RandomUtils.*;
-import static org.junit.jupiter.api.Assertions.*;
-
-/**
-* {@link NotifyMessageServiceImpl} 的单元测试类
-*
-* @author iailab
-*/
-@Import(NotifyMessageServiceImpl.class)
-public class NotifyMessageServiceImplTest extends BaseDbUnitTest {
-
-    @Resource
-    private NotifyMessageServiceImpl notifyMessageService;
-
-    @Resource
-    private NotifyMessageMapper notifyMessageMapper;
-
-    @Test
-    public void testCreateNotifyMessage_success() {
-        // 准备参数
-        Long userId = randomLongId();
-        Integer userType = randomEle(UserTypeEnum.values()).getValue();
-        NotifyTemplateDO template = randomPojo(NotifyTemplateDO.class);
-        String templateContent = randomString();
-        Map<String, Object> templateParams = randomTemplateParams();
-        // mock 方法
-
-        // 调用
-        Long messageId = notifyMessageService.createNotifyMessage(userId, userType,
-                template, templateContent, templateParams);
-        // 断言
-        NotifyMessageDO message = notifyMessageMapper.selectById(messageId);
-        assertNotNull(message);
-        assertEquals(userId, message.getUserId());
-        assertEquals(userType, message.getUserType());
-        assertEquals(template.getId(), message.getTemplateId());
-        assertEquals(template.getCode(), message.getTemplateCode());
-        assertEquals(template.getType(), message.getTemplateType());
-        assertEquals(template.getNickname(), message.getTemplateNickname());
-        assertEquals(templateContent, message.getTemplateContent());
-        assertEquals(templateParams, message.getTemplateParams());
-        assertEquals(false, message.getReadStatus());
-        assertNull(message.getReadTime());
-    }
-
-    @Test
-    public void testGetNotifyMessagePage() {
-       // mock 数据
-       NotifyMessageDO dbNotifyMessage = randomPojo(NotifyMessageDO.class, o -> { // 等会查询到
-           o.setUserId(1L);
-           o.setUserType(UserTypeEnum.ADMIN.getValue());
-           o.setTemplateCode("test_01");
-           o.setTemplateType(10);
-           o.setCreateTime(buildTime(2022, 1, 2));
-           o.setTemplateParams(randomTemplateParams());
-       });
-       notifyMessageMapper.insert(dbNotifyMessage);
-       // 测试 userId 不匹配
-       notifyMessageMapper.insert(cloneIgnoreId(dbNotifyMessage, o -> o.setUserId(2L)));
-       // 测试 userType 不匹配
-       notifyMessageMapper.insert(cloneIgnoreId(dbNotifyMessage, o -> o.setUserType(UserTypeEnum.MEMBER.getValue())));
-       // 测试 templateCode 不匹配
-       notifyMessageMapper.insert(cloneIgnoreId(dbNotifyMessage, o -> o.setTemplateCode("test_11")));
-       // 测试 templateType 不匹配
-       notifyMessageMapper.insert(cloneIgnoreId(dbNotifyMessage, o -> o.setTemplateType(20)));
-       // 测试 createTime 不匹配
-       notifyMessageMapper.insert(cloneIgnoreId(dbNotifyMessage, o -> o.setCreateTime(buildTime(2022, 2, 1))));
-       // 准备参数
-       NotifyMessagePageReqVO reqVO = new NotifyMessagePageReqVO();
-       reqVO.setUserId(1L);
-       reqVO.setUserType(UserTypeEnum.ADMIN.getValue());
-       reqVO.setTemplateCode("est_01");
-       reqVO.setTemplateType(10);
-       reqVO.setCreateTime(buildBetweenTime(2022, 1, 1, 2022, 1, 10));
-
-       // 调用
-       PageResult<NotifyMessageDO> pageResult = notifyMessageService.getNotifyMessagePage(reqVO);
-       // 断言
-       assertEquals(1, pageResult.getTotal());
-       assertEquals(1, pageResult.getList().size());
-       assertPojoEquals(dbNotifyMessage, pageResult.getList().get(0));
-    }
-
-    @Test
-    public void testGetNotifyMessage() {
-        // mock 数据
-        NotifyMessageDO dbNotifyMessage = randomPojo(NotifyMessageDO.class,
-                o -> o.setTemplateParams(randomTemplateParams()));
-        notifyMessageMapper.insert(dbNotifyMessage);
-        // 准备参数
-        Long id = dbNotifyMessage.getId();
-
-        // 调用
-        NotifyMessageDO notifyMessage = notifyMessageService.getNotifyMessage(id);
-        assertPojoEquals(dbNotifyMessage, notifyMessage);
-    }
-
-    @Test
-    public void testGetMyNotifyMessagePage() {
-        // mock 数据
-        NotifyMessageDO dbNotifyMessage = randomPojo(NotifyMessageDO.class, o -> { // 等会查询到
-            o.setUserId(1L);
-            o.setUserType(UserTypeEnum.ADMIN.getValue());
-            o.setReadStatus(true);
-            o.setCreateTime(buildTime(2022, 1, 2));
-            o.setTemplateParams(randomTemplateParams());
-        });
-        notifyMessageMapper.insert(dbNotifyMessage);
-        // 测试 userId 不匹配
-        notifyMessageMapper.insert(cloneIgnoreId(dbNotifyMessage, o -> o.setUserId(2L)));
-        // 测试 userType 不匹配
-        notifyMessageMapper.insert(cloneIgnoreId(dbNotifyMessage, o -> o.setUserType(UserTypeEnum.MEMBER.getValue())));
-        // 测试 readStatus 不匹配
-        notifyMessageMapper.insert(cloneIgnoreId(dbNotifyMessage, o -> o.setReadStatus(false)));
-        // 测试 createTime 不匹配
-        notifyMessageMapper.insert(cloneIgnoreId(dbNotifyMessage, o -> o.setCreateTime(buildTime(2022, 2, 1))));
-        // 准备参数
-        Long userId = 1L;
-        Integer userType = UserTypeEnum.ADMIN.getValue();
-        NotifyMessageMyPageReqVO reqVO = new NotifyMessageMyPageReqVO();
-        reqVO.setReadStatus(true);
-        reqVO.setCreateTime(buildBetweenTime(2022, 1, 1, 2022, 1, 10));
-
-        // 调用
-        PageResult<NotifyMessageDO> pageResult = notifyMessageService.getMyMyNotifyMessagePage(reqVO, userId, userType);
-        // 断言
-        assertEquals(1, pageResult.getTotal());
-        assertEquals(1, pageResult.getList().size());
-        assertPojoEquals(dbNotifyMessage, pageResult.getList().get(0));
-    }
-
-    @Test
-    public void testGetUnreadNotifyMessageList() {
-        SqlConstants.init(DbType.MYSQL);
-        // mock 数据
-        NotifyMessageDO dbNotifyMessage = randomPojo(NotifyMessageDO.class, o -> { // 等会查询到
-            o.setUserId(1L);
-            o.setUserType(UserTypeEnum.ADMIN.getValue());
-            o.setReadStatus(false);
-            o.setTemplateParams(randomTemplateParams());
-        });
-        notifyMessageMapper.insert(dbNotifyMessage);
-        // 测试 userId 不匹配
-        notifyMessageMapper.insert(cloneIgnoreId(dbNotifyMessage, o -> o.setUserId(2L)));
-        // 测试 userType 不匹配
-        notifyMessageMapper.insert(cloneIgnoreId(dbNotifyMessage, o -> o.setUserType(UserTypeEnum.MEMBER.getValue())));
-        // 测试 readStatus 不匹配
-        notifyMessageMapper.insert(cloneIgnoreId(dbNotifyMessage, o -> o.setReadStatus(true)));
-        // 准备参数
-        Long userId = 1L;
-        Integer userType = UserTypeEnum.ADMIN.getValue();
-        Integer size = 10;
-
-        // 调用
-        List<NotifyMessageDO> list = notifyMessageService.getUnreadNotifyMessageList(userId, userType, size);
-        // 断言
-        assertEquals(1, list.size());
-        assertPojoEquals(dbNotifyMessage, list.get(0));
-    }
-
-    @Test
-    public void testGetUnreadNotifyMessageCount() {
-        SqlConstants.init(DbType.MYSQL);
-        // mock 数据
-        NotifyMessageDO dbNotifyMessage = randomPojo(NotifyMessageDO.class, o -> { // 等会查询到
-            o.setUserId(1L);
-            o.setUserType(UserTypeEnum.ADMIN.getValue());
-            o.setReadStatus(false);
-            o.setTemplateParams(randomTemplateParams());
-        });
-        notifyMessageMapper.insert(dbNotifyMessage);
-        // 测试 userId 不匹配
-        notifyMessageMapper.insert(cloneIgnoreId(dbNotifyMessage, o -> o.setUserId(2L)));
-        // 测试 userType 不匹配
-        notifyMessageMapper.insert(cloneIgnoreId(dbNotifyMessage, o -> o.setUserType(UserTypeEnum.MEMBER.getValue())));
-        // 测试 readStatus 不匹配
-        notifyMessageMapper.insert(cloneIgnoreId(dbNotifyMessage, o -> o.setReadStatus(true)));
-        // 准备参数
-        Long userId = 1L;
-        Integer userType = UserTypeEnum.ADMIN.getValue();
-
-        // 调用,并断言
-        assertEquals(1, notifyMessageService.getUnreadNotifyMessageCount(userId, userType));
-    }
-
-    @Test
-    public void testUpdateNotifyMessageRead() {
-        // mock 数据
-        NotifyMessageDO dbNotifyMessage = randomPojo(NotifyMessageDO.class, o -> { // 等会查询到
-            o.setUserId(1L);
-            o.setUserType(UserTypeEnum.ADMIN.getValue());
-            o.setReadStatus(false);
-            o.setReadTime(null);
-            o.setTemplateParams(randomTemplateParams());
-        });
-        notifyMessageMapper.insert(dbNotifyMessage);
-        // 测试 userId 不匹配
-        notifyMessageMapper.insert(cloneIgnoreId(dbNotifyMessage, o -> o.setUserId(2L)));
-        // 测试 userType 不匹配
-        notifyMessageMapper.insert(cloneIgnoreId(dbNotifyMessage, o -> o.setUserType(UserTypeEnum.MEMBER.getValue())));
-        // 测试 readStatus 不匹配
-        notifyMessageMapper.insert(cloneIgnoreId(dbNotifyMessage, o -> o.setReadStatus(true)));
-        // 准备参数
-        Collection<Long> ids = Arrays.asList(dbNotifyMessage.getId(), dbNotifyMessage.getId() + 1,
-                dbNotifyMessage.getId() + 2, dbNotifyMessage.getId() + 3);
-        Long userId = 1L;
-        Integer userType = UserTypeEnum.ADMIN.getValue();
-
-        // 调用
-        int updateCount = notifyMessageService.updateNotifyMessageRead(ids, userId, userType);
-        // 断言
-        assertEquals(1, updateCount);
-        NotifyMessageDO notifyMessage = notifyMessageMapper.selectById(dbNotifyMessage.getId());
-        assertTrue(notifyMessage.getReadStatus());
-        assertNotNull(notifyMessage.getReadTime());
-    }
-
-    @Test
-    public void testUpdateAllNotifyMessageRead() {
-        // mock 数据
-        NotifyMessageDO dbNotifyMessage = randomPojo(NotifyMessageDO.class, o -> { // 等会查询到
-            o.setUserId(1L);
-            o.setUserType(UserTypeEnum.ADMIN.getValue());
-            o.setReadStatus(false);
-            o.setReadTime(null);
-            o.setTemplateParams(randomTemplateParams());
-        });
-        notifyMessageMapper.insert(dbNotifyMessage);
-        // 测试 userId 不匹配
-        notifyMessageMapper.insert(cloneIgnoreId(dbNotifyMessage, o -> o.setUserId(2L)));
-        // 测试 userType 不匹配
-        notifyMessageMapper.insert(cloneIgnoreId(dbNotifyMessage, o -> o.setUserType(UserTypeEnum.MEMBER.getValue())));
-        // 测试 readStatus 不匹配
-        notifyMessageMapper.insert(cloneIgnoreId(dbNotifyMessage, o -> o.setReadStatus(true)));
-        // 准备参数
-        Long userId = 1L;
-        Integer userType = UserTypeEnum.ADMIN.getValue();
-
-        // 调用
-        int updateCount = notifyMessageService.updateAllNotifyMessageRead(userId, userType);
-        // 断言
-        assertEquals(1, updateCount);
-        NotifyMessageDO notifyMessage = notifyMessageMapper.selectById(dbNotifyMessage.getId());
-        assertTrue(notifyMessage.getReadStatus());
-        assertNotNull(notifyMessage.getReadTime());
-    }
-
-    private static Map<String, Object> randomTemplateParams() {
-        return MapUtil.<String, Object>builder().put(randomString(), randomString())
-                .put(randomString(), randomString()).build();
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/notify/NotifySendServiceImplTest.java b/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/notify/NotifySendServiceImplTest.java
deleted file mode 100644
index 69189fe..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/notify/NotifySendServiceImplTest.java
+++ /dev/null
@@ -1,190 +0,0 @@
-package com.iailab.module.system.service.notify;
-
-import cn.hutool.core.map.MapUtil;
-import com.iailab.framework.common.enums.CommonStatusEnum;
-import com.iailab.framework.common.enums.UserTypeEnum;
-import com.iailab.framework.test.core.ut.BaseMockitoUnitTest;
-import com.iailab.module.system.dal.dataobject.notify.NotifyTemplateDO;
-import org.assertj.core.util.Lists;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import static cn.hutool.core.util.RandomUtil.randomEle;
-import static com.iailab.framework.test.core.util.AssertUtils.assertServiceException;
-import static com.iailab.framework.test.core.util.RandomUtils.*;
-import static com.iailab.module.system.enums.ErrorCodeConstants.NOTICE_NOT_FOUND;
-import static com.iailab.module.system.enums.ErrorCodeConstants.NOTIFY_SEND_TEMPLATE_PARAM_MISS;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNull;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.*;
-
-class NotifySendServiceImplTest extends BaseMockitoUnitTest {
-
-    @InjectMocks
-    private NotifySendServiceImpl notifySendService;
-
-    @Mock
-    private NotifyTemplateService notifyTemplateService;
-    @Mock
-    private NotifyMessageService notifyMessageService;
-
-    @Test
-    public void testSendSingleNotifyToAdmin() {
-        // 准备参数
-        Long userId = randomLongId();
-        String templateCode = randomString();
-        Map<String, Object> templateParams = MapUtil.<String, Object>builder().put("code", "1234")
-                .put("op", "login").build();
-        // mock NotifyTemplateService 的方法
-        NotifyTemplateDO template = randomPojo(NotifyTemplateDO.class, o -> {
-            o.setStatus(CommonStatusEnum.ENABLE.getStatus());
-            o.setContent("验证码为{code}, 操作为{op}");
-            o.setParams(Lists.newArrayList("code", "op"));
-        });
-        when(notifyTemplateService.getNotifyTemplateByCodeFromCache(eq(templateCode))).thenReturn(template);
-        String content = randomString();
-        when(notifyTemplateService.formatNotifyTemplateContent(eq(template.getContent()), eq(templateParams)))
-                .thenReturn(content);
-        // mock NotifyMessageService 的方法
-        Long messageId = randomLongId();
-        when(notifyMessageService.createNotifyMessage(eq(userId), eq(UserTypeEnum.ADMIN.getValue()),
-                eq(template), eq(content), eq(templateParams))).thenReturn(messageId);
-
-        // 调用
-        Long resultMessageId = notifySendService.sendSingleNotifyToAdmin(userId, templateCode, templateParams);
-        // 断言
-        assertEquals(messageId, resultMessageId);
-    }
-
-    @Test
-    public void testSendSingleNotifyToMember() {
-        // 准备参数
-        Long userId = randomLongId();
-        String templateCode = randomString();
-        Map<String, Object> templateParams = MapUtil.<String, Object>builder().put("code", "1234")
-                .put("op", "login").build();
-        // mock NotifyTemplateService 的方法
-        NotifyTemplateDO template = randomPojo(NotifyTemplateDO.class, o -> {
-            o.setStatus(CommonStatusEnum.ENABLE.getStatus());
-            o.setContent("验证码为{code}, 操作为{op}");
-            o.setParams(Lists.newArrayList("code", "op"));
-        });
-        when(notifyTemplateService.getNotifyTemplateByCodeFromCache(eq(templateCode))).thenReturn(template);
-        String content = randomString();
-        when(notifyTemplateService.formatNotifyTemplateContent(eq(template.getContent()), eq(templateParams)))
-                .thenReturn(content);
-        // mock NotifyMessageService 的方法
-        Long messageId = randomLongId();
-        when(notifyMessageService.createNotifyMessage(eq(userId), eq(UserTypeEnum.MEMBER.getValue()),
-                eq(template), eq(content), eq(templateParams))).thenReturn(messageId);
-
-        // 调用
-        Long resultMessageId = notifySendService.sendSingleNotifyToMember(userId, templateCode, templateParams);
-        // 断言
-        assertEquals(messageId, resultMessageId);
-    }
-
-    /**
-     * 发送成功,当短信模板开启时
-     */
-    @Test
-    public void testSendSingleNotify_successWhenMailTemplateEnable() {
-        // 准备参数
-        Long userId = randomLongId();
-        Integer userType = randomEle(UserTypeEnum.values()).getValue();
-        String templateCode = randomString();
-        Map<String, Object> templateParams = MapUtil.<String, Object>builder().put("code", "1234")
-                .put("op", "login").build();
-        // mock NotifyTemplateService 的方法
-        NotifyTemplateDO template = randomPojo(NotifyTemplateDO.class, o -> {
-            o.setStatus(CommonStatusEnum.ENABLE.getStatus());
-            o.setContent("验证码为{code}, 操作为{op}");
-            o.setParams(Lists.newArrayList("code", "op"));
-        });
-        when(notifyTemplateService.getNotifyTemplateByCodeFromCache(eq(templateCode))).thenReturn(template);
-        String content = randomString();
-        when(notifyTemplateService.formatNotifyTemplateContent(eq(template.getContent()), eq(templateParams)))
-                .thenReturn(content);
-        // mock NotifyMessageService 的方法
-        Long messageId = randomLongId();
-        when(notifyMessageService.createNotifyMessage(eq(userId), eq(userType),
-                eq(template), eq(content), eq(templateParams))).thenReturn(messageId);
-
-        // 调用
-        Long resultMessageId = notifySendService.sendSingleNotify(userId, userType, templateCode, templateParams);
-        // 断言
-        assertEquals(messageId, resultMessageId);
-    }
-
-    /**
-     * 发送成功,当短信模板关闭时
-     */
-    @Test
-    public void testSendSingleMail_successWhenSmsTemplateDisable() {
-        // 准备参数
-        Long userId = randomLongId();
-        Integer userType = randomEle(UserTypeEnum.values()).getValue();
-        String templateCode = randomString();
-        Map<String, Object> templateParams = MapUtil.<String, Object>builder().put("code", "1234")
-                .put("op", "login").build();
-        // mock NotifyTemplateService 的方法
-        NotifyTemplateDO template = randomPojo(NotifyTemplateDO.class, o -> {
-            o.setStatus(CommonStatusEnum.DISABLE.getStatus());
-            o.setContent("验证码为{code}, 操作为{op}");
-            o.setParams(Lists.newArrayList("code", "op"));
-        });
-        when(notifyTemplateService.getNotifyTemplateByCodeFromCache(eq(templateCode))).thenReturn(template);
-
-        // 调用
-        Long resultMessageId = notifySendService.sendSingleNotify(userId, userType, templateCode, templateParams);
-        // 断言
-        assertNull(resultMessageId);
-        verify(notifyTemplateService, never()).formatNotifyTemplateContent(anyString(), anyMap());
-        verify(notifyMessageService, never()).createNotifyMessage(anyLong(), anyInt(), any(), anyString(), anyMap());
-    }
-
-    @Test
-    public void testCheckMailTemplateValid_notExists() {
-        // 准备参数
-        String templateCode = randomString();
-        // mock 方法
-
-        // 调用,并断言异常
-        assertServiceException(() -> notifySendService.validateNotifyTemplate(templateCode),
-                NOTICE_NOT_FOUND);
-    }
-
-    @Test
-    public void testCheckTemplateParams_paramMiss() {
-        // 准备参数
-        NotifyTemplateDO template = randomPojo(NotifyTemplateDO.class,
-                o -> o.setParams(Lists.newArrayList("code")));
-        Map<String, Object> templateParams = new HashMap<>();
-        // mock 方法
-
-        // 调用,并断言异常
-        assertServiceException(() -> notifySendService.validateTemplateParams(template, templateParams),
-                NOTIFY_SEND_TEMPLATE_PARAM_MISS, "code");
-    }
-
-    @Test
-    public void testSendBatchNotify() {
-        // 准备参数
-        // mock 方法
-
-        // 调用
-        UnsupportedOperationException exception = Assertions.assertThrows(
-                UnsupportedOperationException.class,
-                () -> notifySendService.sendBatchNotify(null, null, null, null, null)
-        );
-        // 断言
-        assertEquals("暂时不支持该操作,感兴趣可以实现该功能哟!", exception.getMessage());
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/notify/NotifyTemplateServiceImplTest.java b/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/notify/NotifyTemplateServiceImplTest.java
deleted file mode 100644
index 1931402..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/notify/NotifyTemplateServiceImplTest.java
+++ /dev/null
@@ -1,178 +0,0 @@
-package com.iailab.module.system.service.notify;
-
-import com.iailab.framework.common.enums.CommonStatusEnum;
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.framework.test.core.ut.BaseDbUnitTest;
-import com.iailab.module.system.controller.admin.notify.vo.template.NotifyTemplatePageReqVO;
-import com.iailab.module.system.controller.admin.notify.vo.template.NotifyTemplateSaveReqVO;
-import com.iailab.module.system.dal.dataobject.notify.NotifyTemplateDO;
-import com.iailab.module.system.dal.mysql.notify.NotifyTemplateMapper;
-import org.junit.jupiter.api.Test;
-import org.springframework.context.annotation.Import;
-
-import javax.annotation.Resource;
-import java.util.HashMap;
-import java.util.Map;
-
-import static com.iailab.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
-import static com.iailab.framework.common.util.date.LocalDateTimeUtils.buildTime;
-import static com.iailab.framework.common.util.object.ObjectUtils.cloneIgnoreId;
-import static com.iailab.framework.test.core.util.AssertUtils.assertPojoEquals;
-import static com.iailab.framework.test.core.util.AssertUtils.assertServiceException;
-import static com.iailab.framework.test.core.util.RandomUtils.*;
-import static com.iailab.module.system.enums.ErrorCodeConstants.NOTIFY_TEMPLATE_NOT_EXISTS;
-import static org.junit.jupiter.api.Assertions.*;
-
-/**
- * {@link NotifyTemplateServiceImpl} 的单元测试类
- *
- * @author iailab
- */
-@Import(NotifyTemplateServiceImpl.class)
-public class NotifyTemplateServiceImplTest extends BaseDbUnitTest {
-
-    @Resource
-    private NotifyTemplateServiceImpl notifyTemplateService;
-
-    @Resource
-    private NotifyTemplateMapper notifyTemplateMapper;
-
-    @Test
-    public void testCreateNotifyTemplate_success() {
-        // 准备参数
-        NotifyTemplateSaveReqVO reqVO = randomPojo(NotifyTemplateSaveReqVO.class,
-                o -> o.setStatus(randomCommonStatus()))
-                .setId(null); // 防止 id 被赋值
-
-        // 调用
-        Long notifyTemplateId = notifyTemplateService.createNotifyTemplate(reqVO);
-        // 断言
-        assertNotNull(notifyTemplateId);
-        // 校验记录的属性是否正确
-        NotifyTemplateDO notifyTemplate = notifyTemplateMapper.selectById(notifyTemplateId);
-        assertPojoEquals(reqVO, notifyTemplate, "id");
-    }
-
-    @Test
-    public void testUpdateNotifyTemplate_success() {
-        // mock 数据
-        NotifyTemplateDO dbNotifyTemplate = randomPojo(NotifyTemplateDO.class);
-        notifyTemplateMapper.insert(dbNotifyTemplate);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        NotifyTemplateSaveReqVO reqVO = randomPojo(NotifyTemplateSaveReqVO.class, o -> {
-            o.setId(dbNotifyTemplate.getId()); // 设置更新的 ID
-            o.setStatus(randomCommonStatus());
-        });
-
-        // 调用
-        notifyTemplateService.updateNotifyTemplate(reqVO);
-        // 校验是否更新正确
-        NotifyTemplateDO notifyTemplate = notifyTemplateMapper.selectById(reqVO.getId()); // 获取最新的
-        assertPojoEquals(reqVO, notifyTemplate);
-    }
-
-    @Test
-    public void testUpdateNotifyTemplate_notExists() {
-        // 准备参数
-        NotifyTemplateSaveReqVO reqVO = randomPojo(NotifyTemplateSaveReqVO.class);
-
-        // 调用, 并断言异常
-        assertServiceException(() -> notifyTemplateService.updateNotifyTemplate(reqVO), NOTIFY_TEMPLATE_NOT_EXISTS);
-    }
-
-    @Test
-    public void testDeleteNotifyTemplate_success() {
-        // mock 数据
-        NotifyTemplateDO dbNotifyTemplate = randomPojo(NotifyTemplateDO.class);
-        notifyTemplateMapper.insert(dbNotifyTemplate);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        Long id = dbNotifyTemplate.getId();
-
-        // 调用
-        notifyTemplateService.deleteNotifyTemplate(id);
-        // 校验数据不存在了
-        assertNull(notifyTemplateMapper.selectById(id));
-    }
-
-    @Test
-    public void testDeleteNotifyTemplate_notExists() {
-        // 准备参数
-        Long id = randomLongId();
-
-        // 调用, 并断言异常
-        assertServiceException(() -> notifyTemplateService.deleteNotifyTemplate(id), NOTIFY_TEMPLATE_NOT_EXISTS);
-    }
-
-    @Test
-    public void testGetNotifyTemplatePage() {
-        // mock 数据
-        NotifyTemplateDO dbNotifyTemplate = randomPojo(NotifyTemplateDO.class, o -> { // 等会查询到
-            o.setName("芋头");
-            o.setCode("test_01");
-            o.setStatus(CommonStatusEnum.ENABLE.getStatus());
-            o.setCreateTime(buildTime(2022, 2, 3));
-        });
-        notifyTemplateMapper.insert(dbNotifyTemplate);
-        // 测试 name 不匹配
-        notifyTemplateMapper.insert(cloneIgnoreId(dbNotifyTemplate, o -> o.setName("投")));
-        // 测试 code 不匹配
-        notifyTemplateMapper.insert(cloneIgnoreId(dbNotifyTemplate, o -> o.setCode("test_02")));
-        // 测试 status 不匹配
-        notifyTemplateMapper.insert(cloneIgnoreId(dbNotifyTemplate, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
-        // 测试 createTime 不匹配
-        notifyTemplateMapper.insert(cloneIgnoreId(dbNotifyTemplate, o -> o.setCreateTime(buildTime(2022, 1, 5))));
-        // 准备参数
-        NotifyTemplatePageReqVO reqVO = new NotifyTemplatePageReqVO();
-        reqVO.setName("芋");
-        reqVO.setCode("est_01");
-        reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
-        reqVO.setCreateTime(buildBetweenTime(2022, 2, 1, 2022, 2, 5));
-
-        // 调用
-        PageResult<NotifyTemplateDO> pageResult = notifyTemplateService.getNotifyTemplatePage(reqVO);
-        // 断言
-        assertEquals(1, pageResult.getTotal());
-        assertEquals(1, pageResult.getList().size());
-        assertPojoEquals(dbNotifyTemplate, pageResult.getList().get(0));
-    }
-
-    @Test
-    public void testGetNotifyTemplate() {
-        // mock 数据
-        NotifyTemplateDO dbNotifyTemplate = randomPojo(NotifyTemplateDO.class);
-        notifyTemplateMapper.insert(dbNotifyTemplate);
-        // 准备参数
-        Long id = dbNotifyTemplate.getId();
-
-        // 调用
-        NotifyTemplateDO notifyTemplate = notifyTemplateService.getNotifyTemplate(id);
-        // 断言
-        assertPojoEquals(dbNotifyTemplate, notifyTemplate);
-    }
-
-    @Test
-    public void testGetNotifyTemplateByCodeFromCache() {
-        // mock 数据
-        NotifyTemplateDO dbNotifyTemplate = randomPojo(NotifyTemplateDO.class);
-        notifyTemplateMapper.insert(dbNotifyTemplate);
-        // 准备参数
-        String code = dbNotifyTemplate.getCode();
-
-        // 调用
-        NotifyTemplateDO notifyTemplate = notifyTemplateService.getNotifyTemplateByCodeFromCache(code);
-        // 断言
-        assertPojoEquals(dbNotifyTemplate, notifyTemplate);
-    }
-
-    @Test
-    public void testFormatNotifyTemplateContent() {
-        // 准备参数
-        Map<String, Object> params = new HashMap<>();
-        params.put("name", "小红");
-        params.put("what", "饭");
-
-        // 调用,并断言
-        assertEquals("小红,你好,饭吃了吗?",
-                notifyTemplateService.formatNotifyTemplateContent("{name},你好,{what}吃了吗?", params));
-    }
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/oauth2/OAuth2ApproveServiceImplTest.java b/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/oauth2/OAuth2ApproveServiceImplTest.java
deleted file mode 100644
index 6ffdfcc..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/oauth2/OAuth2ApproveServiceImplTest.java
+++ /dev/null
@@ -1,269 +0,0 @@
-package com.iailab.module.system.service.oauth2;
-
-import cn.hutool.core.date.LocalDateTimeUtil;
-import cn.hutool.core.util.ObjectUtil;
-import com.iailab.framework.common.enums.UserTypeEnum;
-import com.iailab.framework.common.util.date.DateUtils;
-import com.iailab.framework.test.core.ut.BaseDbUnitTest;
-import com.iailab.module.system.dal.dataobject.oauth2.OAuth2ApproveDO;
-import com.iailab.module.system.dal.dataobject.oauth2.OAuth2ClientDO;
-import com.iailab.module.system.dal.mysql.oauth2.OAuth2ApproveMapper;
-import org.assertj.core.util.Lists;
-import org.junit.jupiter.api.Test;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.context.annotation.Import;
-
-import javax.annotation.Resource;
-import java.time.LocalDateTime;
-import java.time.ZoneId;
-import java.time.temporal.ChronoUnit;
-import java.util.*;
-
-import static cn.hutool.core.util.RandomUtil.*;
-import static com.iailab.framework.test.core.util.AssertUtils.assertPojoEquals;
-import static com.iailab.framework.test.core.util.RandomUtils.randomString;
-import static com.iailab.framework.test.core.util.RandomUtils.*;
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.when;
-
-/**
- * {@link OAuth2ApproveServiceImpl} 的单元测试类
- *
- * @author iailab
- */
-@Import(OAuth2ApproveServiceImpl.class)
-public class OAuth2ApproveServiceImplTest extends BaseDbUnitTest {
-
-    @Resource
-    private OAuth2ApproveServiceImpl oauth2ApproveService;
-
-    @Resource
-    private OAuth2ApproveMapper oauth2ApproveMapper;
-
-    @MockBean
-    private OAuth2ClientService oauth2ClientService;
-
-    @Test
-    public void checkForPreApproval_clientAutoApprove() {
-        // 准备参数
-        Long userId = randomLongId();
-        Integer userType = randomEle(UserTypeEnum.values()).getValue();
-        String clientId = randomString();
-        List<String> requestedScopes = Lists.newArrayList("read");
-        // mock 方法
-        when(oauth2ClientService.validOAuthClientFromCache(eq(clientId)))
-                .thenReturn(randomPojo(OAuth2ClientDO.class).setAutoApproveScopes(requestedScopes));
-
-        // 调用
-        boolean success = oauth2ApproveService.checkForPreApproval(userId, userType,
-                clientId, requestedScopes);
-        // 断言
-        assertTrue(success);
-        List<OAuth2ApproveDO> result = oauth2ApproveMapper.selectList();
-        assertEquals(1, result.size());
-        assertEquals(userId, result.get(0).getUserId());
-        assertEquals(userType, result.get(0).getUserType());
-        assertEquals(clientId, result.get(0).getClientId());
-        assertEquals("read", result.get(0).getScope());
-        assertTrue(result.get(0).getApproved());
-        assertFalse(DateUtils.isExpired(result.get(0).getExpiresTime()));
-    }
-
-    @Test
-    public void checkForPreApproval_approve() {
-        // 准备参数
-        Long userId = randomLongId();
-        Integer userType = randomEle(UserTypeEnum.values()).getValue();
-        String clientId = randomString();
-        List<String> requestedScopes = Lists.newArrayList("read");
-        // mock 方法
-        when(oauth2ClientService.validOAuthClientFromCache(eq(clientId)))
-                .thenReturn(randomPojo(OAuth2ClientDO.class).setAutoApproveScopes(null));
-        // mock 数据
-        OAuth2ApproveDO approve = randomPojo(OAuth2ApproveDO.class).setUserId(userId)
-                .setUserType(userType).setClientId(clientId).setScope("read")
-                .setExpiresTime(LocalDateTimeUtil.offset(LocalDateTime.now(), 1L, ChronoUnit.DAYS)).setApproved(true); // 同意
-        oauth2ApproveMapper.insert(approve);
-
-        // 调用
-        boolean success = oauth2ApproveService.checkForPreApproval(userId, userType,
-                clientId, requestedScopes);
-        // 断言
-        assertTrue(success);
-    }
-
-    @Test
-    public void checkForPreApproval_reject() {
-        // 准备参数
-        Long userId = randomLongId();
-        Integer userType = randomEle(UserTypeEnum.values()).getValue();
-        String clientId = randomString();
-        List<String> requestedScopes = Lists.newArrayList("read");
-        // mock 方法
-        when(oauth2ClientService.validOAuthClientFromCache(eq(clientId)))
-                .thenReturn(randomPojo(OAuth2ClientDO.class).setAutoApproveScopes(null));
-        // mock 数据
-        OAuth2ApproveDO approve = randomPojo(OAuth2ApproveDO.class).setUserId(userId)
-                .setUserType(userType).setClientId(clientId).setScope("read")
-                .setExpiresTime(LocalDateTimeUtil.offset(LocalDateTime.now(), 1L, ChronoUnit.DAYS)).setApproved(false); // 拒绝
-        oauth2ApproveMapper.insert(approve);
-
-        // 调用
-        boolean success = oauth2ApproveService.checkForPreApproval(userId, userType,
-                clientId, requestedScopes);
-        // 断言
-        assertFalse(success);
-    }
-
-    @Test
-    public void testUpdateAfterApproval_none() {
-        // 准备参数
-        Long userId = randomLongId();
-        Integer userType = randomEle(UserTypeEnum.values()).getValue();
-        String clientId = randomString();
-
-        // 调用
-        boolean success = oauth2ApproveService.updateAfterApproval(userId, userType, clientId,
-                null);
-        // 断言
-        assertTrue(success);
-        List<OAuth2ApproveDO> result = oauth2ApproveMapper.selectList();
-        assertEquals(0, result.size());
-    }
-
-    @Test
-    public void testUpdateAfterApproval_approved() {
-        // 准备参数
-        Long userId = randomLongId();
-        Integer userType = randomEle(UserTypeEnum.values()).getValue();
-        String clientId = randomString();
-        Map<String, Boolean> requestedScopes = new LinkedHashMap<>(); // 有序,方便判断
-        requestedScopes.put("read", true);
-        requestedScopes.put("write", false);
-        // mock 方法
-
-        // 调用
-        boolean success = oauth2ApproveService.updateAfterApproval(userId, userType, clientId,
-                requestedScopes);
-        // 断言
-        assertTrue(success);
-        List<OAuth2ApproveDO> result = oauth2ApproveMapper.selectList();
-        assertEquals(2, result.size());
-        // read
-        assertEquals(userId, result.get(0).getUserId());
-        assertEquals(userType, result.get(0).getUserType());
-        assertEquals(clientId, result.get(0).getClientId());
-        assertEquals("read", result.get(0).getScope());
-        assertTrue(result.get(0).getApproved());
-        assertFalse(DateUtils.isExpired(result.get(0).getExpiresTime()));
-        // write
-        assertEquals(userId, result.get(1).getUserId());
-        assertEquals(userType, result.get(1).getUserType());
-        assertEquals(clientId, result.get(1).getClientId());
-        assertEquals("write", result.get(1).getScope());
-        assertFalse(result.get(1).getApproved());
-        assertFalse(DateUtils.isExpired(result.get(1).getExpiresTime()));
-    }
-
-    @Test
-    public void testUpdateAfterApproval_reject() {
-        // 准备参数
-        Long userId = randomLongId();
-        Integer userType = randomEle(UserTypeEnum.values()).getValue();
-        String clientId = randomString();
-        Map<String, Boolean> requestedScopes = new LinkedHashMap<>();
-        requestedScopes.put("write", false);
-        // mock 方法
-
-        // 调用
-        boolean success = oauth2ApproveService.updateAfterApproval(userId, userType, clientId,
-                requestedScopes);
-        // 断言
-        assertFalse(success);
-        List<OAuth2ApproveDO> result = oauth2ApproveMapper.selectList();
-        assertEquals(1, result.size());
-        // write
-        assertEquals(userId, result.get(0).getUserId());
-        assertEquals(userType, result.get(0).getUserType());
-        assertEquals(clientId, result.get(0).getClientId());
-        assertEquals("write", result.get(0).getScope());
-        assertFalse(result.get(0).getApproved());
-        assertFalse(DateUtils.isExpired(result.get(0).getExpiresTime()));
-    }
-
-    @Test
-    public void testGetApproveList() {
-        // 准备参数
-        Long userId = 10L;
-        Integer userType = UserTypeEnum.ADMIN.getValue();
-        String clientId = randomString();
-        // mock 数据
-        OAuth2ApproveDO approve = randomPojo(OAuth2ApproveDO.class).setUserId(userId)
-                .setUserType(userType).setClientId(clientId).setExpiresTime(LocalDateTimeUtil.offset(LocalDateTime.now(), 1L, ChronoUnit.DAYS));
-        oauth2ApproveMapper.insert(approve); // 未过期
-        oauth2ApproveMapper.insert(ObjectUtil.clone(approve).setId(null)
-                .setExpiresTime(LocalDateTimeUtil.offset(LocalDateTime.now(), -1L, ChronoUnit.DAYS))); // 已过期
-
-        // 调用
-        List<OAuth2ApproveDO> result = oauth2ApproveService.getApproveList(userId, userType, clientId);
-        // 断言
-        assertEquals(1, result.size());
-        assertPojoEquals(approve, result.get(0));
-    }
-
-    @Test
-    public void testSaveApprove_insert() {
-        // 准备参数
-        Long userId = randomLongId();
-        Integer userType = randomEle(UserTypeEnum.values()).getValue();
-        String clientId = randomString();
-        String scope = randomString();
-        Boolean approved = randomBoolean();
-        LocalDateTime expireTime = LocalDateTime.ofInstant(randomDay(1, 30).toInstant(), ZoneId.systemDefault());
-        // mock 方法
-
-        // 调用
-        oauth2ApproveService.saveApprove(userId, userType, clientId,
-                scope, approved, expireTime);
-        // 断言
-        List<OAuth2ApproveDO> result = oauth2ApproveMapper.selectList();
-        assertEquals(1, result.size());
-        assertEquals(userId, result.get(0).getUserId());
-        assertEquals(userType, result.get(0).getUserType());
-        assertEquals(clientId, result.get(0).getClientId());
-        assertEquals(scope, result.get(0).getScope());
-        assertEquals(approved, result.get(0).getApproved());
-        assertEquals(expireTime, result.get(0).getExpiresTime());
-    }
-
-    @Test
-    public void testSaveApprove_update() {
-        // mock 数据
-        OAuth2ApproveDO approve = randomPojo(OAuth2ApproveDO.class);
-        oauth2ApproveMapper.insert(approve);
-        // 准备参数
-        Long userId = approve.getUserId();
-        Integer userType = approve.getUserType();
-        String clientId = approve.getClientId();
-        String scope = approve.getScope();
-        Boolean approved = randomBoolean();
-        LocalDateTime expireTime = LocalDateTime.ofInstant(randomDay(1, 30).toInstant(), ZoneId.systemDefault());
-        // mock 方法
-
-        // 调用
-        oauth2ApproveService.saveApprove(userId, userType, clientId,
-                scope, approved, expireTime);
-        // 断言
-        List<OAuth2ApproveDO> result = oauth2ApproveMapper.selectList();
-        assertEquals(1, result.size());
-        assertEquals(approve.getId(), result.get(0).getId());
-        assertEquals(userId, result.get(0).getUserId());
-        assertEquals(userType, result.get(0).getUserType());
-        assertEquals(clientId, result.get(0).getClientId());
-        assertEquals(scope, result.get(0).getScope());
-        assertEquals(approved, result.get(0).getApproved());
-        assertEquals(expireTime, result.get(0).getExpiresTime());
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/oauth2/OAuth2ClientServiceImplTest.java b/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/oauth2/OAuth2ClientServiceImplTest.java
deleted file mode 100644
index 1f9b493..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/oauth2/OAuth2ClientServiceImplTest.java
+++ /dev/null
@@ -1,220 +0,0 @@
-package com.iailab.module.system.service.oauth2;
-
-import cn.hutool.extra.spring.SpringUtil;
-import com.iailab.framework.common.enums.CommonStatusEnum;
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.framework.test.core.ut.BaseDbUnitTest;
-import com.iailab.module.system.controller.admin.oauth2.vo.client.OAuth2ClientPageReqVO;
-import com.iailab.module.system.controller.admin.oauth2.vo.client.OAuth2ClientSaveReqVO;
-import com.iailab.module.system.dal.dataobject.oauth2.OAuth2ClientDO;
-import com.iailab.module.system.dal.mysql.oauth2.OAuth2ClientMapper;
-import org.junit.jupiter.api.Test;
-import org.mockito.MockedStatic;
-import org.springframework.context.annotation.Import;
-
-import javax.annotation.Resource;
-import java.util.Collections;
-
-import static com.iailab.framework.common.util.object.ObjectUtils.cloneIgnoreId;
-import static com.iailab.framework.test.core.util.AssertUtils.assertPojoEquals;
-import static com.iailab.framework.test.core.util.AssertUtils.assertServiceException;
-import static com.iailab.framework.test.core.util.RandomUtils.*;
-import static com.iailab.module.system.enums.ErrorCodeConstants.*;
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mockStatic;
-
-/**
- * {@link OAuth2ClientServiceImpl} 的单元测试类
- *
- * @author iailab
- */
-@Import(OAuth2ClientServiceImpl.class)
-public class OAuth2ClientServiceImplTest extends BaseDbUnitTest {
-
-    @Resource
-    private OAuth2ClientServiceImpl oauth2ClientService;
-
-    @Resource
-    private OAuth2ClientMapper oauth2ClientMapper;
-
-    @Test
-    public void testCreateOAuth2Client_success() {
-        // 准备参数
-        OAuth2ClientSaveReqVO reqVO = randomPojo(OAuth2ClientSaveReqVO.class,
-                o -> o.setLogo(randomString()))
-                .setId(null); // 防止 id 被赋值
-
-        // 调用
-        Long oauth2ClientId = oauth2ClientService.createOAuth2Client(reqVO);
-        // 断言
-        assertNotNull(oauth2ClientId);
-        // 校验记录的属性是否正确
-        OAuth2ClientDO oAuth2Client = oauth2ClientMapper.selectById(oauth2ClientId);
-        assertPojoEquals(reqVO, oAuth2Client, "id");
-    }
-
-    @Test
-    public void testUpdateOAuth2Client_success() {
-        // mock 数据
-        OAuth2ClientDO dbOAuth2Client = randomPojo(OAuth2ClientDO.class);
-        oauth2ClientMapper.insert(dbOAuth2Client);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        OAuth2ClientSaveReqVO reqVO = randomPojo(OAuth2ClientSaveReqVO.class, o -> {
-            o.setId(dbOAuth2Client.getId()); // 设置更新的 ID
-            o.setLogo(randomString());
-        });
-
-        // 调用
-        oauth2ClientService.updateOAuth2Client(reqVO);
-        // 校验是否更新正确
-        OAuth2ClientDO oAuth2Client = oauth2ClientMapper.selectById(reqVO.getId()); // 获取最新的
-        assertPojoEquals(reqVO, oAuth2Client);
-    }
-
-    @Test
-    public void testUpdateOAuth2Client_notExists() {
-        // 准备参数
-        OAuth2ClientSaveReqVO reqVO = randomPojo(OAuth2ClientSaveReqVO.class);
-
-        // 调用, 并断言异常
-        assertServiceException(() -> oauth2ClientService.updateOAuth2Client(reqVO), OAUTH2_CLIENT_NOT_EXISTS);
-    }
-
-    @Test
-    public void testDeleteOAuth2Client_success() {
-        // mock 数据
-        OAuth2ClientDO dbOAuth2Client = randomPojo(OAuth2ClientDO.class);
-        oauth2ClientMapper.insert(dbOAuth2Client);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        Long id = dbOAuth2Client.getId();
-
-        // 调用
-        oauth2ClientService.deleteOAuth2Client(id);
-        // 校验数据不存在了
-        assertNull(oauth2ClientMapper.selectById(id));
-    }
-
-    @Test
-    public void testDeleteOAuth2Client_notExists() {
-        // 准备参数
-        Long id = randomLongId();
-
-        // 调用, 并断言异常
-        assertServiceException(() -> oauth2ClientService.deleteOAuth2Client(id), OAUTH2_CLIENT_NOT_EXISTS);
-    }
-
-    @Test
-    public void testValidateClientIdExists_withId() {
-        // mock 数据
-        OAuth2ClientDO client = randomPojo(OAuth2ClientDO.class).setClientId("tudou");
-        oauth2ClientMapper.insert(client);
-        // 准备参数
-        Long id = randomLongId();
-        String clientId = "tudou";
-
-        // 调用,不会报错
-        assertServiceException(() -> oauth2ClientService.validateClientIdExists(id, clientId), OAUTH2_CLIENT_EXISTS);
-    }
-
-    @Test
-    public void testValidateClientIdExists_noId() {
-        // mock 数据
-        OAuth2ClientDO client = randomPojo(OAuth2ClientDO.class).setClientId("tudou");
-        oauth2ClientMapper.insert(client);
-        // 准备参数
-        String clientId = "tudou";
-
-        // 调用,不会报错
-        assertServiceException(() -> oauth2ClientService.validateClientIdExists(null, clientId), OAUTH2_CLIENT_EXISTS);
-    }
-
-    @Test
-    public void testGetOAuth2Client() {
-        // mock 数据
-        OAuth2ClientDO clientDO = randomPojo(OAuth2ClientDO.class);
-        oauth2ClientMapper.insert(clientDO);
-        // 准备参数
-        Long id = clientDO.getId();
-
-        // 调用,并断言
-        OAuth2ClientDO dbClientDO = oauth2ClientService.getOAuth2Client(id);
-        assertPojoEquals(clientDO, dbClientDO);
-    }
-
-    @Test
-    public void testGetOAuth2ClientFromCache() {
-        // mock 数据
-        OAuth2ClientDO clientDO = randomPojo(OAuth2ClientDO.class);
-        oauth2ClientMapper.insert(clientDO);
-        // 准备参数
-        String clientId = clientDO.getClientId();
-
-        // 调用,并断言
-        OAuth2ClientDO dbClientDO = oauth2ClientService.getOAuth2ClientFromCache(clientId);
-        assertPojoEquals(clientDO, dbClientDO);
-    }
-
-    @Test
-    public void testGetOAuth2ClientPage() {
-        // mock 数据
-        OAuth2ClientDO dbOAuth2Client = randomPojo(OAuth2ClientDO.class, o -> { // 等会查询到
-            o.setName("潜龙");
-            o.setStatus(CommonStatusEnum.ENABLE.getStatus());
-        });
-        oauth2ClientMapper.insert(dbOAuth2Client);
-        // 测试 name 不匹配
-        oauth2ClientMapper.insert(cloneIgnoreId(dbOAuth2Client, o -> o.setName("凤凰")));
-        // 测试 status 不匹配
-        oauth2ClientMapper.insert(cloneIgnoreId(dbOAuth2Client, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
-        // 准备参数
-        OAuth2ClientPageReqVO reqVO = new OAuth2ClientPageReqVO();
-        reqVO.setName("龙");
-        reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
-
-        // 调用
-        PageResult<OAuth2ClientDO> pageResult = oauth2ClientService.getOAuth2ClientPage(reqVO);
-        // 断言
-        assertEquals(1, pageResult.getTotal());
-        assertEquals(1, pageResult.getList().size());
-        assertPojoEquals(dbOAuth2Client, pageResult.getList().get(0));
-    }
-
-    @Test
-    public void testValidOAuthClientFromCache() {
-        try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) {
-            springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(OAuth2ClientServiceImpl.class)))
-                    .thenReturn(oauth2ClientService);
-
-            // mock 方法
-            OAuth2ClientDO client = randomPojo(OAuth2ClientDO.class).setClientId("default")
-                    .setStatus(CommonStatusEnum.ENABLE.getStatus());
-            oauth2ClientMapper.insert(client);
-            OAuth2ClientDO client02 = randomPojo(OAuth2ClientDO.class).setClientId("disable")
-                    .setStatus(CommonStatusEnum.DISABLE.getStatus());
-            oauth2ClientMapper.insert(client02);
-
-            // 调用,并断言
-            assertServiceException(() -> oauth2ClientService.validOAuthClientFromCache(randomString(),
-                    null, null, null, null), OAUTH2_CLIENT_NOT_EXISTS);
-            assertServiceException(() -> oauth2ClientService.validOAuthClientFromCache("disable",
-                    null, null, null, null), OAUTH2_CLIENT_DISABLE);
-            assertServiceException(() -> oauth2ClientService.validOAuthClientFromCache("default",
-                    randomString(), null, null, null), OAUTH2_CLIENT_CLIENT_SECRET_ERROR);
-            assertServiceException(() -> oauth2ClientService.validOAuthClientFromCache("default",
-                    null, randomString(), null, null), OAUTH2_CLIENT_AUTHORIZED_GRANT_TYPE_NOT_EXISTS);
-            assertServiceException(() -> oauth2ClientService.validOAuthClientFromCache("default",
-                    null, null, Collections.singleton(randomString()), null), OAUTH2_CLIENT_SCOPE_OVER);
-            assertServiceException(() -> oauth2ClientService.validOAuthClientFromCache("default",
-                    null, null, null, "test"), OAUTH2_CLIENT_REDIRECT_URI_NOT_MATCH, "test");
-            // 成功调用(1:参数完整)
-            OAuth2ClientDO result = oauth2ClientService.validOAuthClientFromCache(client.getClientId(), client.getSecret(),
-                    client.getAuthorizedGrantTypes().get(0), client.getScopes(), client.getRedirectUris().get(0));
-            assertPojoEquals(client, result);
-            // 成功调用(2:只有 clientId 参数)
-            result = oauth2ClientService.validOAuthClientFromCache(client.getClientId());
-            assertPojoEquals(client, result);
-        }
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/oauth2/OAuth2CodeServiceImplTest.java b/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/oauth2/OAuth2CodeServiceImplTest.java
deleted file mode 100644
index 2822873..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/oauth2/OAuth2CodeServiceImplTest.java
+++ /dev/null
@@ -1,99 +0,0 @@
-package com.iailab.module.system.service.oauth2;
-
-import cn.hutool.core.util.RandomUtil;
-import com.iailab.framework.common.enums.UserTypeEnum;
-import com.iailab.framework.common.util.date.DateUtils;
-import com.iailab.framework.test.core.ut.BaseDbUnitTest;
-import com.iailab.module.system.dal.dataobject.oauth2.OAuth2CodeDO;
-import com.iailab.module.system.dal.mysql.oauth2.OAuth2CodeMapper;
-import org.assertj.core.util.Lists;
-import org.junit.jupiter.api.Test;
-import org.springframework.context.annotation.Import;
-
-import javax.annotation.Resource;
-import java.time.LocalDateTime;
-import java.util.List;
-
-import static com.iailab.framework.test.core.util.AssertUtils.assertPojoEquals;
-import static com.iailab.framework.test.core.util.AssertUtils.assertServiceException;
-import static com.iailab.framework.test.core.util.RandomUtils.*;
-import static com.iailab.module.system.enums.ErrorCodeConstants.OAUTH2_CODE_EXPIRE;
-import static com.iailab.module.system.enums.ErrorCodeConstants.OAUTH2_CODE_NOT_EXISTS;
-import static org.junit.jupiter.api.Assertions.*;
-
-/**
- * {@link OAuth2CodeServiceImpl} 的单元测试类
- *
- * @author iailab
- */
-@Import(OAuth2CodeServiceImpl.class)
-class OAuth2CodeServiceImplTest extends BaseDbUnitTest {
-
-    @Resource
-    private OAuth2CodeServiceImpl oauth2CodeService;
-
-    @Resource
-    private OAuth2CodeMapper oauth2CodeMapper;
-
-    @Test
-    public void testCreateAuthorizationCode() {
-        // 准备参数
-        Long userId = randomLongId();
-        Integer userType = RandomUtil.randomEle(UserTypeEnum.values()).getValue();
-        String clientId = randomString();
-        List<String> scopes = Lists.newArrayList("read", "write");
-        String redirectUri = randomString();
-        String state = randomString();
-
-        // 调用
-        OAuth2CodeDO codeDO = oauth2CodeService.createAuthorizationCode(userId, userType, clientId,
-                scopes, redirectUri, state);
-        // 断言
-        OAuth2CodeDO dbCodeDO = oauth2CodeMapper.selectByCode(codeDO.getCode());
-        assertPojoEquals(codeDO, dbCodeDO, "createTime", "updateTime", "deleted");
-        assertEquals(userId, codeDO.getUserId());
-        assertEquals(userType, codeDO.getUserType());
-        assertEquals(clientId, codeDO.getClientId());
-        assertEquals(scopes, codeDO.getScopes());
-        assertEquals(redirectUri, codeDO.getRedirectUri());
-        assertEquals(state, codeDO.getState());
-        assertFalse(DateUtils.isExpired(codeDO.getExpiresTime()));
-    }
-
-    @Test
-    public void testConsumeAuthorizationCode_null() {
-        // 调用,并断言
-        assertServiceException(() -> oauth2CodeService.consumeAuthorizationCode(randomString()),
-                OAUTH2_CODE_NOT_EXISTS);
-    }
-
-    @Test
-    public void testConsumeAuthorizationCode_expired() {
-        // 准备参数
-        String code = "test_code";
-        // mock 数据
-        OAuth2CodeDO codeDO = randomPojo(OAuth2CodeDO.class).setCode(code)
-                .setExpiresTime(LocalDateTime.now().minusDays(1));
-        oauth2CodeMapper.insert(codeDO);
-
-        // 调用,并断言
-        assertServiceException(() -> oauth2CodeService.consumeAuthorizationCode(code),
-                OAUTH2_CODE_EXPIRE);
-    }
-
-    @Test
-    public void testConsumeAuthorizationCode_success() {
-        // 准备参数
-        String code = "test_code";
-        // mock 数据
-        OAuth2CodeDO codeDO = randomPojo(OAuth2CodeDO.class).setCode(code)
-                .setExpiresTime(LocalDateTime.now().plusDays(1));
-        oauth2CodeMapper.insert(codeDO);
-
-        // 调用
-        OAuth2CodeDO result = oauth2CodeService.consumeAuthorizationCode(code);
-        assertPojoEquals(codeDO, result);
-        assertNull(oauth2CodeMapper.selectByCode(code));
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/oauth2/OAuth2GrantServiceImplTest.java b/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/oauth2/OAuth2GrantServiceImplTest.java
deleted file mode 100644
index 871a493..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/oauth2/OAuth2GrantServiceImplTest.java
+++ /dev/null
@@ -1,173 +0,0 @@
-package com.iailab.module.system.service.oauth2;
-
-import com.iailab.framework.common.enums.UserTypeEnum;
-import com.iailab.framework.test.core.ut.BaseMockitoUnitTest;
-import com.iailab.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
-import com.iailab.module.system.dal.dataobject.oauth2.OAuth2CodeDO;
-import com.iailab.module.system.dal.dataobject.user.AdminUserDO;
-import com.iailab.module.system.service.auth.AdminAuthService;
-import com.google.common.collect.Lists;
-import org.junit.jupiter.api.Test;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-
-import java.util.List;
-
-import static cn.hutool.core.util.RandomUtil.randomEle;
-import static com.iailab.framework.test.core.util.AssertUtils.assertPojoEquals;
-import static com.iailab.framework.test.core.util.RandomUtils.*;
-import static java.util.Collections.emptyList;
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.when;
-
-/**
- * {@link OAuth2GrantServiceImpl} 的单元测试
- *
- * @author iailab
- */
-public class OAuth2GrantServiceImplTest extends BaseMockitoUnitTest {
-
-    @InjectMocks
-    private OAuth2GrantServiceImpl oauth2GrantService;
-
-    @Mock
-    private OAuth2TokenService oauth2TokenService;
-    @Mock
-    private OAuth2CodeService oauth2CodeService;
-    @Mock
-    private AdminAuthService adminAuthService;
-
-    @Test
-    public void testGrantImplicit() {
-        // 准备参数
-        Long userId = randomLongId();
-        Integer userType = randomEle(UserTypeEnum.values()).getValue();
-        String clientId = randomString();
-        List<String> scopes = Lists.newArrayList("read", "write");
-        // mock 方法
-        OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class);
-        when(oauth2TokenService.createAccessToken(eq(userId), eq(userType),
-                eq(clientId), eq(scopes))).thenReturn(accessTokenDO);
-
-        // 调用,并断言
-        assertPojoEquals(accessTokenDO, oauth2GrantService.grantImplicit(
-                userId, userType, clientId, scopes));
-    }
-
-    @Test
-    public void testGrantAuthorizationCodeForCode() {
-        // 准备参数
-        Long userId = randomLongId();
-        Integer userType = randomEle(UserTypeEnum.values()).getValue();
-        String clientId = randomString();
-        List<String> scopes = Lists.newArrayList("read", "write");
-        String redirectUri = randomString();
-        String state = randomString();
-        // mock 方法
-        OAuth2CodeDO codeDO = randomPojo(OAuth2CodeDO.class);
-        when(oauth2CodeService.createAuthorizationCode(eq(userId), eq(userType),
-                eq(clientId), eq(scopes), eq(redirectUri), eq(state))).thenReturn(codeDO);
-
-        // 调用,并断言
-        assertEquals(codeDO.getCode(), oauth2GrantService.grantAuthorizationCodeForCode(userId, userType,
-                clientId, scopes, redirectUri, state));
-    }
-
-    @Test
-    public void testGrantAuthorizationCodeForAccessToken() {
-        // 准备参数
-        String clientId = randomString();
-        String code = randomString();
-        List<String> scopes = Lists.newArrayList("read", "write");
-        String redirectUri = randomString();
-        String state = randomString();
-        // mock 方法(code)
-        OAuth2CodeDO codeDO = randomPojo(OAuth2CodeDO.class, o -> {
-            o.setClientId(clientId);
-            o.setRedirectUri(redirectUri);
-            o.setState(state);
-            o.setScopes(scopes);
-        });
-        when(oauth2CodeService.consumeAuthorizationCode(eq(code))).thenReturn(codeDO);
-        // mock 方法(创建令牌)
-        OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class);
-        when(oauth2TokenService.createAccessToken(eq(codeDO.getUserId()), eq(codeDO.getUserType()),
-                eq(codeDO.getClientId()), eq(codeDO.getScopes()))).thenReturn(accessTokenDO);
-
-        // 调用,并断言
-        assertPojoEquals(accessTokenDO, oauth2GrantService.grantAuthorizationCodeForAccessToken(
-                clientId, code, redirectUri, state));
-    }
-
-    @Test
-    public void testGrantPassword() {
-        // 准备参数
-        String username = randomString();
-        String password = randomString();
-        String clientId = randomString();
-        List<String> scopes = Lists.newArrayList("read", "write");
-        // mock 方法(认证)
-        AdminUserDO user = randomPojo(AdminUserDO.class);
-        when(adminAuthService.authenticate(eq(username), eq(password))).thenReturn(user);
-        // mock 方法(访问令牌)
-        OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class);
-        when(oauth2TokenService.createAccessToken(eq(user.getId()), eq(UserTypeEnum.ADMIN.getValue()),
-                eq(clientId), eq(scopes))).thenReturn(accessTokenDO);
-
-        // 调用,并断言
-        assertPojoEquals(accessTokenDO, oauth2GrantService.grantPassword(
-                username, password, clientId, scopes));
-    }
-
-    @Test
-    public void testGrantRefreshToken() {
-        // 准备参数
-        String refreshToken = randomString();
-        String clientId = randomString();
-        // mock 方法
-        OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class);
-        when(oauth2TokenService.refreshAccessToken(eq(refreshToken), eq(clientId)))
-                .thenReturn(accessTokenDO);
-
-        // 调用,并断言
-        assertPojoEquals(accessTokenDO, oauth2GrantService.grantRefreshToken(
-                refreshToken, clientId));
-    }
-
-    @Test
-    public void testGrantClientCredentials() {
-        assertThrows(UnsupportedOperationException.class,
-                () -> oauth2GrantService.grantClientCredentials(randomString(), emptyList()),
-                "暂时不支持 client_credentials 授权模式");
-    }
-
-    @Test
-    public void testRevokeToken_clientIdError() {
-        // 准备参数
-        String clientId = randomString();
-        String accessToken = randomString();
-        // mock 方法
-        OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class);
-        when(oauth2TokenService.getAccessToken(eq(accessToken))).thenReturn(accessTokenDO);
-
-        // 调用,并断言
-        assertFalse(oauth2GrantService.revokeToken(clientId, accessToken));
-    }
-
-    @Test
-    public void testRevokeToken_success() {
-        // 准备参数
-        String clientId = randomString();
-        String accessToken = randomString();
-        // mock 方法(访问令牌)
-        OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class).setClientId(clientId);
-        when(oauth2TokenService.getAccessToken(eq(accessToken))).thenReturn(accessTokenDO);
-        // mock 方法(移除)
-        when(oauth2TokenService.removeAccessToken(eq(accessToken))).thenReturn(accessTokenDO);
-
-        // 调用,并断言
-        assertTrue(oauth2GrantService.revokeToken(clientId, accessToken));
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/oauth2/OAuth2TokenServiceImplTest.java b/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/oauth2/OAuth2TokenServiceImplTest.java
deleted file mode 100644
index 7079e52..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/oauth2/OAuth2TokenServiceImplTest.java
+++ /dev/null
@@ -1,303 +0,0 @@
-package com.iailab.module.system.service.oauth2;
-
-import cn.hutool.core.date.LocalDateTimeUtil;
-import com.iailab.framework.common.enums.UserTypeEnum;
-import com.iailab.framework.common.exception.ErrorCode;
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.framework.common.util.date.DateUtils;
-import com.iailab.framework.tenant.core.context.TenantContextHolder;
-import com.iailab.framework.test.core.ut.BaseDbAndRedisUnitTest;
-import com.iailab.module.system.controller.admin.oauth2.vo.token.OAuth2AccessTokenPageReqVO;
-import com.iailab.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
-import com.iailab.module.system.dal.dataobject.oauth2.OAuth2ClientDO;
-import com.iailab.module.system.dal.dataobject.oauth2.OAuth2RefreshTokenDO;
-import com.iailab.module.system.dal.dataobject.user.AdminUserDO;
-import com.iailab.module.system.dal.mysql.oauth2.OAuth2AccessTokenMapper;
-import com.iailab.module.system.dal.mysql.oauth2.OAuth2RefreshTokenMapper;
-import com.iailab.module.system.dal.redis.oauth2.OAuth2AccessTokenRedisDAO;
-import com.iailab.module.system.service.user.AdminUserService;
-import org.assertj.core.util.Lists;
-import org.junit.jupiter.api.Test;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.context.annotation.Import;
-
-import javax.annotation.Resource;
-import java.time.LocalDateTime;
-import java.util.List;
-
-import static com.iailab.framework.common.util.object.ObjectUtils.cloneIgnoreId;
-import static com.iailab.framework.test.core.util.AssertUtils.assertPojoEquals;
-import static com.iailab.framework.test.core.util.AssertUtils.assertServiceException;
-import static com.iailab.framework.test.core.util.RandomUtils.*;
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.when;
-
-/**
- * {@link OAuth2TokenServiceImpl} 的单元测试类
- *
- * @author iailab
- */
-@Import({OAuth2TokenServiceImpl.class, OAuth2AccessTokenRedisDAO.class})
-public class OAuth2TokenServiceImplTest extends BaseDbAndRedisUnitTest {
-
-    @Resource
-    private OAuth2TokenServiceImpl oauth2TokenService;
-
-    @Resource
-    private OAuth2AccessTokenMapper oauth2AccessTokenMapper;
-    @Resource
-    private OAuth2RefreshTokenMapper oauth2RefreshTokenMapper;
-
-    @Resource
-    private OAuth2AccessTokenRedisDAO oauth2AccessTokenRedisDAO;
-
-    @MockBean
-    private OAuth2ClientService oauth2ClientService;
-    @MockBean
-    private AdminUserService adminUserService;
-
-    @Test
-    public void testCreateAccessToken() {
-        TenantContextHolder.setTenantId(0L);
-        // 准备参数
-        Long userId = randomLongId();
-        Integer userType = UserTypeEnum.ADMIN.getValue();
-        String clientId = randomString();
-        List<String> scopes = Lists.newArrayList("read", "write");
-        // mock 方法
-        OAuth2ClientDO clientDO = randomPojo(OAuth2ClientDO.class).setClientId(clientId)
-                .setAccessTokenValiditySeconds(30).setRefreshTokenValiditySeconds(60);
-        when(oauth2ClientService.validOAuthClientFromCache(eq(clientId))).thenReturn(clientDO);
-        // mock 数据(用户)
-        AdminUserDO user = randomPojo(AdminUserDO.class);
-        when(adminUserService.getUser(userId)).thenReturn(user);
-
-        // 调用
-        OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.createAccessToken(userId, userType, clientId, scopes);
-        // 断言访问令牌
-        OAuth2AccessTokenDO dbAccessTokenDO = oauth2AccessTokenMapper.selectByAccessToken(accessTokenDO.getAccessToken());
-        assertPojoEquals(accessTokenDO, dbAccessTokenDO, "createTime", "updateTime", "deleted");
-        assertEquals(userId, accessTokenDO.getUserId());
-        assertEquals(userType, accessTokenDO.getUserType());
-        assertEquals(2, accessTokenDO.getUserInfo().size());
-        assertEquals(user.getNickname(), accessTokenDO.getUserInfo().get("nickname"));
-        assertEquals(user.getDeptId().toString(), accessTokenDO.getUserInfo().get("deptId"));
-        assertEquals(clientId, accessTokenDO.getClientId());
-        assertEquals(scopes, accessTokenDO.getScopes());
-        assertFalse(DateUtils.isExpired(accessTokenDO.getExpiresTime()));
-        // 断言访问令牌的缓存
-        OAuth2AccessTokenDO redisAccessTokenDO = oauth2AccessTokenRedisDAO.get(accessTokenDO.getAccessToken());
-        assertPojoEquals(accessTokenDO, redisAccessTokenDO, "createTime", "updateTime", "deleted");
-        // 断言刷新令牌
-        OAuth2RefreshTokenDO refreshTokenDO = oauth2RefreshTokenMapper.selectList().get(0);
-        assertPojoEquals(accessTokenDO, refreshTokenDO, "id", "expiresTime", "createTime", "updateTime", "deleted");
-        assertFalse(DateUtils.isExpired(refreshTokenDO.getExpiresTime()));
-    }
-
-    @Test
-    public void testRefreshAccessToken_null() {
-        // 准备参数
-        String refreshToken = randomString();
-        String clientId = randomString();
-        // mock 方法
-
-        // 调用,并断言
-        assertServiceException(() -> oauth2TokenService.refreshAccessToken(refreshToken, clientId),
-                new ErrorCode(400, "无效的刷新令牌"));
-    }
-
-    @Test
-    public void testRefreshAccessToken_clientIdError() {
-        // 准备参数
-        String refreshToken = randomString();
-        String clientId = randomString();
-        // mock 方法
-        OAuth2ClientDO clientDO = randomPojo(OAuth2ClientDO.class).setClientId(clientId);
-        when(oauth2ClientService.validOAuthClientFromCache(eq(clientId))).thenReturn(clientDO);
-        // mock 数据(访问令牌)
-        OAuth2RefreshTokenDO refreshTokenDO = randomPojo(OAuth2RefreshTokenDO.class)
-                .setRefreshToken(refreshToken).setClientId("error");
-        oauth2RefreshTokenMapper.insert(refreshTokenDO);
-
-        // 调用,并断言
-        assertServiceException(() -> oauth2TokenService.refreshAccessToken(refreshToken, clientId),
-                new ErrorCode(400, "刷新令牌的客户端编号不正确"));
-    }
-
-    @Test
-    public void testRefreshAccessToken_expired() {
-        // 准备参数
-        String refreshToken = randomString();
-        String clientId = randomString();
-        // mock 方法
-        OAuth2ClientDO clientDO = randomPojo(OAuth2ClientDO.class).setClientId(clientId);
-        when(oauth2ClientService.validOAuthClientFromCache(eq(clientId))).thenReturn(clientDO);
-        // mock 数据(访问令牌)
-        OAuth2RefreshTokenDO refreshTokenDO = randomPojo(OAuth2RefreshTokenDO.class)
-                .setRefreshToken(refreshToken).setClientId(clientId)
-                .setExpiresTime(LocalDateTime.now().minusDays(1));
-        oauth2RefreshTokenMapper.insert(refreshTokenDO);
-
-        // 调用,并断言
-        assertServiceException(() -> oauth2TokenService.refreshAccessToken(refreshToken, clientId),
-                new ErrorCode(401, "刷新令牌已过期"));
-        assertEquals(0, oauth2RefreshTokenMapper.selectCount());
-    }
-
-    @Test
-    public void testRefreshAccessToken_success() {
-        TenantContextHolder.setTenantId(0L);
-        // 准备参数
-        String refreshToken = randomString();
-        String clientId = randomString();
-        // mock 方法
-        OAuth2ClientDO clientDO = randomPojo(OAuth2ClientDO.class).setClientId(clientId)
-                .setAccessTokenValiditySeconds(30);
-        when(oauth2ClientService.validOAuthClientFromCache(eq(clientId))).thenReturn(clientDO);
-        // mock 数据(访问令牌)
-        OAuth2RefreshTokenDO refreshTokenDO = randomPojo(OAuth2RefreshTokenDO.class)
-                .setRefreshToken(refreshToken).setClientId(clientId)
-                .setExpiresTime(LocalDateTime.now().plusDays(1))
-                .setUserType(UserTypeEnum.ADMIN.getValue());
-        oauth2RefreshTokenMapper.insert(refreshTokenDO);
-        // mock 数据(访问令牌)
-        OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class).setRefreshToken(refreshToken)
-                .setUserType(refreshTokenDO.getUserType());
-        oauth2AccessTokenMapper.insert(accessTokenDO);
-        oauth2AccessTokenRedisDAO.set(accessTokenDO);
-        // mock 数据(用户)
-        AdminUserDO user = randomPojo(AdminUserDO.class);
-        when(adminUserService.getUser(refreshTokenDO.getUserId())).thenReturn(user);
-
-        // 调用
-        OAuth2AccessTokenDO newAccessTokenDO = oauth2TokenService.refreshAccessToken(refreshToken, clientId);
-        // 断言,老的访问令牌被删除
-        assertNull(oauth2AccessTokenMapper.selectByAccessToken(accessTokenDO.getAccessToken()));
-        assertNull(oauth2AccessTokenRedisDAO.get(accessTokenDO.getAccessToken()));
-        // 断言,新的访问令牌
-        OAuth2AccessTokenDO dbAccessTokenDO = oauth2AccessTokenMapper.selectByAccessToken(newAccessTokenDO.getAccessToken());
-        assertPojoEquals(newAccessTokenDO, dbAccessTokenDO, "createTime", "updateTime", "deleted");
-        assertPojoEquals(newAccessTokenDO, refreshTokenDO, "id", "expiresTime", "createTime", "updateTime", "deleted",
-                "creator", "updater");
-        assertFalse(DateUtils.isExpired(newAccessTokenDO.getExpiresTime()));
-        // 断言,新的访问令牌的缓存
-        OAuth2AccessTokenDO redisAccessTokenDO = oauth2AccessTokenRedisDAO.get(newAccessTokenDO.getAccessToken());
-        assertPojoEquals(newAccessTokenDO, redisAccessTokenDO, "createTime", "updateTime", "deleted");
-    }
-
-    @Test
-    public void testGetAccessToken() {
-        // mock 数据(访问令牌)
-        OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class)
-                .setExpiresTime(LocalDateTime.now().plusDays(1));
-        oauth2AccessTokenMapper.insert(accessTokenDO);
-        // 准备参数
-        String accessToken = accessTokenDO.getAccessToken();
-
-        // 调用
-        OAuth2AccessTokenDO result = oauth2TokenService.getAccessToken(accessToken);
-        // 断言
-        assertPojoEquals(accessTokenDO, result, "createTime", "updateTime", "deleted",
-                "creator", "updater");
-        assertPojoEquals(accessTokenDO, oauth2AccessTokenRedisDAO.get(accessToken), "createTime", "updateTime", "deleted",
-                "creator", "updater");
-    }
-
-    @Test
-    public void testCheckAccessToken_null() {
-        // 调研,并断言
-        assertServiceException(() -> oauth2TokenService.checkAccessToken(randomString()),
-                new ErrorCode(401, "访问令牌不存在"));
-    }
-
-    @Test
-    public void testCheckAccessToken_expired() {
-        // mock 数据(访问令牌)
-        OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class)
-                .setExpiresTime(LocalDateTime.now().minusDays(1));
-        oauth2AccessTokenMapper.insert(accessTokenDO);
-        // 准备参数
-        String accessToken = accessTokenDO.getAccessToken();
-
-        // 调研,并断言
-        assertServiceException(() -> oauth2TokenService.checkAccessToken(accessToken),
-                new ErrorCode(401, "访问令牌已过期"));
-    }
-
-    @Test
-    public void testCheckAccessToken_success() {
-        // mock 数据(访问令牌)
-        OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class)
-                .setExpiresTime(LocalDateTime.now().plusDays(1));
-        oauth2AccessTokenMapper.insert(accessTokenDO);
-        // 准备参数
-        String accessToken = accessTokenDO.getAccessToken();
-
-        // 调研,并断言
-        OAuth2AccessTokenDO result = oauth2TokenService.getAccessToken(accessToken);
-        // 断言
-        assertPojoEquals(accessTokenDO, result, "createTime", "updateTime", "deleted",
-                "creator", "updater");
-    }
-
-    @Test
-    public void testRemoveAccessToken_null() {
-        // 调用,并断言
-        assertNull(oauth2TokenService.removeAccessToken(randomString()));
-    }
-
-    @Test
-    public void testRemoveAccessToken_success() {
-        // mock 数据(访问令牌)
-        OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class)
-                .setExpiresTime(LocalDateTime.now().plusDays(1));
-        oauth2AccessTokenMapper.insert(accessTokenDO);
-        // mock 数据(刷新令牌)
-        OAuth2RefreshTokenDO refreshTokenDO = randomPojo(OAuth2RefreshTokenDO.class)
-                .setRefreshToken(accessTokenDO.getRefreshToken());
-        oauth2RefreshTokenMapper.insert(refreshTokenDO);
-        // 调用
-        OAuth2AccessTokenDO result = oauth2TokenService.removeAccessToken(accessTokenDO.getAccessToken());
-        assertPojoEquals(accessTokenDO, result, "createTime", "updateTime", "deleted",
-                "creator", "updater");
-        // 断言数据
-        assertNull(oauth2AccessTokenMapper.selectByAccessToken(accessTokenDO.getAccessToken()));
-        assertNull(oauth2RefreshTokenMapper.selectByRefreshToken(accessTokenDO.getRefreshToken()));
-        assertNull(oauth2AccessTokenRedisDAO.get(accessTokenDO.getAccessToken()));
-    }
-
-
-    @Test
-    public void testGetAccessTokenPage() {
-        // mock 数据
-        OAuth2AccessTokenDO dbAccessToken = randomPojo(OAuth2AccessTokenDO.class, o -> { // 等会查询到
-            o.setUserId(10L);
-            o.setUserType(1);
-            o.setClientId("test_client");
-            o.setExpiresTime(LocalDateTime.now().plusDays(1));
-        });
-        oauth2AccessTokenMapper.insert(dbAccessToken);
-        // 测试 userId 不匹配
-        oauth2AccessTokenMapper.insert(cloneIgnoreId(dbAccessToken, o -> o.setUserId(20L)));
-        // 测试 userType 不匹配
-        oauth2AccessTokenMapper.insert(cloneIgnoreId(dbAccessToken, o -> o.setUserType(2)));
-        // 测试 userType 不匹配
-        oauth2AccessTokenMapper.insert(cloneIgnoreId(dbAccessToken, o -> o.setClientId("it_client")));
-        // 测试 expireTime 不匹配
-        oauth2AccessTokenMapper.insert(cloneIgnoreId(dbAccessToken, o -> o.setExpiresTime(LocalDateTimeUtil.now())));
-        // 准备参数
-        OAuth2AccessTokenPageReqVO reqVO = new OAuth2AccessTokenPageReqVO();
-        reqVO.setUserId(10L);
-        reqVO.setUserType(1);
-        reqVO.setClientId("test");
-
-        // 调用
-        PageResult<OAuth2AccessTokenDO> pageResult = oauth2TokenService.getAccessTokenPage(reqVO);
-        // 断言
-        assertEquals(1, pageResult.getTotal());
-        assertEquals(1, pageResult.getList().size());
-        assertPojoEquals(dbAccessToken, pageResult.getList().get(0));
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/permission/MenuServiceImplTest.java b/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/permission/MenuServiceImplTest.java
deleted file mode 100644
index f8b8ed8..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/permission/MenuServiceImplTest.java
+++ /dev/null
@@ -1,331 +0,0 @@
-package com.iailab.module.system.service.permission;
-
-import com.iailab.framework.common.enums.CommonStatusEnum;
-import com.iailab.framework.test.core.ut.BaseDbUnitTest;
-import com.iailab.module.system.controller.admin.permission.vo.menu.MenuListReqVO;
-import com.iailab.module.system.controller.admin.permission.vo.menu.MenuSaveVO;
-import com.iailab.module.system.dal.dataobject.permission.MenuDO;
-import com.iailab.module.system.dal.mysql.permission.MenuMapper;
-import com.iailab.module.system.enums.permission.MenuTypeEnum;
-import com.iailab.module.system.service.tenant.TenantService;
-import org.junit.jupiter.api.Test;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.context.annotation.Import;
-
-import javax.annotation.Resource;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-
-import static com.iailab.framework.common.util.collection.SetUtils.asSet;
-import static com.iailab.framework.common.util.object.ObjectUtils.cloneIgnoreId;
-import static com.iailab.framework.test.core.util.AssertUtils.assertPojoEquals;
-import static com.iailab.framework.test.core.util.AssertUtils.assertServiceException;
-import static com.iailab.framework.test.core.util.RandomUtils.*;
-import static com.iailab.module.system.dal.dataobject.permission.MenuDO.ID_ROOT;
-import static com.iailab.module.system.enums.ErrorCodeConstants.*;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNull;
-import static org.mockito.ArgumentMatchers.argThat;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.verify;
-
-@Import(MenuServiceImpl.class)
-public class MenuServiceImplTest extends BaseDbUnitTest {
-
-    @Resource
-    private MenuServiceImpl menuService;
-
-    @Resource
-    private MenuMapper menuMapper;
-
-    @MockBean
-    private PermissionService permissionService;
-    @MockBean
-    private TenantService tenantService;
-
-    @Test
-    public void testCreateMenu_success() {
-        // mock 数据(构造父菜单)
-        MenuDO menuDO = buildMenuDO(MenuTypeEnum.MENU,
-                "parent", 0L);
-        menuMapper.insert(menuDO);
-        Long parentId = menuDO.getId();
-        // 准备参数
-        MenuSaveVO reqVO = randomPojo(MenuSaveVO.class, o -> {
-            o.setParentId(parentId);
-            o.setName("testSonName");
-            o.setType(MenuTypeEnum.MENU.getType());
-        }).setId(null); // 防止 id 被赋值
-        Long menuId = menuService.createMenu(reqVO);
-
-        // 校验记录的属性是否正确
-        MenuDO dbMenu = menuMapper.selectById(menuId);
-        assertPojoEquals(reqVO, dbMenu, "id");
-    }
-
-    @Test
-    public void testUpdateMenu_success() {
-        // mock 数据(构造父子菜单)
-        MenuDO sonMenuDO = createParentAndSonMenu();
-        Long sonId = sonMenuDO.getId();
-        // 准备参数
-        MenuSaveVO reqVO = randomPojo(MenuSaveVO.class, o -> {
-            o.setId(sonId);
-            o.setName("testSonName"); // 修改名字
-            o.setParentId(sonMenuDO.getParentId());
-            o.setType(MenuTypeEnum.MENU.getType());
-        });
-
-        // 调用
-        menuService.updateMenu(reqVO);
-        // 校验记录的属性是否正确
-        MenuDO dbMenu = menuMapper.selectById(sonId);
-        assertPojoEquals(reqVO, dbMenu);
-    }
-
-    @Test
-    public void testUpdateMenu_sonIdNotExist() {
-        // 准备参数
-        MenuSaveVO reqVO = randomPojo(MenuSaveVO.class);
-        // 调用,并断言异常
-        assertServiceException(() -> menuService.updateMenu(reqVO), MENU_NOT_EXISTS);
-    }
-
-    @Test
-    public void testDeleteMenu_success() {
-        // mock 数据
-        MenuDO menuDO = randomPojo(MenuDO.class);
-        menuMapper.insert(menuDO);
-        // 准备参数
-        Long id = menuDO.getId();
-
-        // 调用
-        menuService.deleteMenu(id);
-        // 断言
-        MenuDO dbMenuDO = menuMapper.selectById(id);
-        assertNull(dbMenuDO);
-        verify(permissionService).processMenuDeleted(id);
-    }
-
-    @Test
-    public void testDeleteMenu_menuNotExist() {
-        assertServiceException(() -> menuService.deleteMenu(randomLongId()),
-                MENU_NOT_EXISTS);
-    }
-
-    @Test
-    public void testDeleteMenu_existChildren() {
-        // mock 数据(构造父子菜单)
-        MenuDO sonMenu = createParentAndSonMenu();
-        // 准备参数
-        Long parentId = sonMenu.getParentId();
-
-        // 调用并断言异常
-        assertServiceException(() -> menuService.deleteMenu(parentId), MENU_EXISTS_CHILDREN);
-    }
-
-    @Test
-    public void testGetMenuList_all() {
-        // mock 数据
-        MenuDO menu100 = randomPojo(MenuDO.class);
-        menuMapper.insert(menu100);
-        MenuDO menu101 = randomPojo(MenuDO.class);
-        menuMapper.insert(menu101);
-        // 准备参数
-
-        // 调用
-        List<MenuDO> list = menuService.getMenuList();
-        // 断言
-        assertEquals(2, list.size());
-        assertPojoEquals(menu100, list.get(0));
-        assertPojoEquals(menu101, list.get(1));
-    }
-
-    @Test
-    public void testGetMenuList() {
-        // mock 数据
-        MenuDO menuDO = randomPojo(MenuDO.class, o -> o.setName("iailab").setStatus(CommonStatusEnum.ENABLE.getStatus()));
-        menuMapper.insert(menuDO);
-        // 测试 status 不匹配
-        menuMapper.insert(cloneIgnoreId(menuDO, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
-        // 测试 name 不匹配
-        menuMapper.insert(cloneIgnoreId(menuDO, o -> o.setName("艿")));
-        // 准备参数
-        MenuListReqVO reqVO = new MenuListReqVO().setName("芋").setStatus(CommonStatusEnum.ENABLE.getStatus());
-
-        // 调用
-        List<MenuDO> result = menuService.getMenuList(reqVO);
-        // 断言
-        assertEquals(1, result.size());
-        assertPojoEquals(menuDO, result.get(0));
-    }
-
-    @Test
-    public void testGetMenuListByTenant() {
-        // mock 数据
-        MenuDO menu100 = randomPojo(MenuDO.class, o -> o.setId(100L).setStatus(CommonStatusEnum.ENABLE.getStatus()));
-        menuMapper.insert(menu100);
-        MenuDO menu101 = randomPojo(MenuDO.class, o -> o.setId(101L).setStatus(CommonStatusEnum.DISABLE.getStatus()));
-        menuMapper.insert(menu101);
-        MenuDO menu102 = randomPojo(MenuDO.class, o -> o.setId(102L).setStatus(CommonStatusEnum.ENABLE.getStatus()));
-        menuMapper.insert(menu102);
-        // mock 过滤菜单
-        Set<Long> menuIds = asSet(100L, 101L);
-        doNothing().when(tenantService).handleTenantMenu(argThat(handler -> {
-            handler.handle(menuIds);
-            return true;
-        }));
-        // 准备参数
-        MenuListReqVO reqVO = new MenuListReqVO().setStatus(CommonStatusEnum.ENABLE.getStatus());
-
-        // 调用
-        List<MenuDO> result = menuService.getMenuListByTenant(reqVO);
-        // 断言
-        assertEquals(1, result.size());
-        assertPojoEquals(menu100, result.get(0));
-    }
-
-    @Test
-    public void testGetMenuIdListByPermissionFromCache() {
-        // mock 数据
-        MenuDO menu100 = randomPojo(MenuDO.class);
-        menuMapper.insert(menu100);
-        MenuDO menu101 = randomPojo(MenuDO.class);
-        menuMapper.insert(menu101);
-        // 准备参数
-        String permission = menu100.getPermission();
-
-        // 调用
-        List<Long> ids = menuService.getMenuIdListByPermissionFromCache(permission);
-        // 断言
-        assertEquals(1, ids.size());
-        assertEquals(menu100.getId(), ids.get(0));
-    }
-
-    @Test
-    public void testGetMenuList_ids() {
-        // mock 数据
-        MenuDO menu100 = randomPojo(MenuDO.class);
-        menuMapper.insert(menu100);
-        MenuDO menu101 = randomPojo(MenuDO.class);
-        menuMapper.insert(menu101);
-        // 准备参数
-        Collection<Long> ids = Collections.singleton(menu100.getId());
-
-        // 调用
-        List<MenuDO> list = menuService.getMenuList(ids);
-        // 断言
-        assertEquals(1, list.size());
-        assertPojoEquals(menu100, list.get(0));
-    }
-
-    @Test
-    public void testGetMenu() {
-        // mock 数据
-        MenuDO menu = randomPojo(MenuDO.class);
-        menuMapper.insert(menu);
-        // 准备参数
-        Long id = menu.getId();
-
-        // 调用
-        MenuDO dbMenu = menuService.getMenu(id);
-        // 断言
-        assertPojoEquals(menu, dbMenu);
-    }
-
-    @Test
-    public void testValidateParentMenu_success() {
-        // mock 数据
-        MenuDO menuDO = buildMenuDO(MenuTypeEnum.MENU, "parent", 0L);
-        menuMapper.insert(menuDO);
-        // 准备参数
-        Long parentId = menuDO.getId();
-
-        // 调用,无需断言
-        menuService.validateParentMenu(parentId, null);
-    }
-
-    @Test
-    public void testValidateParentMenu_canNotSetSelfToBeParent() {
-        // 调用,并断言异常
-        assertServiceException(() -> menuService.validateParentMenu(1L, 1L),
-                MENU_PARENT_ERROR);
-    }
-
-    @Test
-    public void testValidateParentMenu_parentNotExist() {
-        // 调用,并断言异常
-        assertServiceException(() -> menuService.validateParentMenu(randomLongId(), null),
-                MENU_PARENT_NOT_EXISTS);
-    }
-
-    @Test
-    public void testValidateParentMenu_parentTypeError() {
-        // mock 数据
-        MenuDO menuDO = buildMenuDO(MenuTypeEnum.BUTTON, "parent", 0L);
-        menuMapper.insert(menuDO);
-        // 准备参数
-        Long parentId = menuDO.getId();
-
-        // 调用,并断言异常
-        assertServiceException(() -> menuService.validateParentMenu(parentId, null),
-                MENU_PARENT_NOT_DIR_OR_MENU);
-    }
-
-    @Test
-    public void testValidateMenu_success() {
-        // mock 父子菜单
-        MenuDO sonMenu = createParentAndSonMenu();
-        // 准备参数
-        Long parentId = sonMenu.getParentId();
-        Long otherSonMenuId = randomLongId();
-        String otherSonMenuName = randomString();
-
-        // 调用,无需断言
-        menuService.validateMenu(parentId, otherSonMenuName, otherSonMenuId);
-    }
-
-    @Test
-    public void testValidateMenu_sonMenuNameDuplicate() {
-        // mock 父子菜单
-        MenuDO sonMenu = createParentAndSonMenu();
-        // 准备参数
-        Long parentId = sonMenu.getParentId();
-        Long otherSonMenuId = randomLongId();
-        String otherSonMenuName = sonMenu.getName(); //相同名称
-
-        // 调用,并断言异常
-        assertServiceException(() -> menuService.validateMenu(parentId, otherSonMenuName, otherSonMenuId),
-                MENU_NAME_DUPLICATE);
-    }
-
-    // ====================== 初始化方法 ======================
-
-    /**
-     * 插入父子菜单,返回子菜单
-     *
-     * @return 子菜单
-     */
-    private MenuDO createParentAndSonMenu() {
-        // 构造父子菜单
-        MenuDO parentMenuDO = buildMenuDO(MenuTypeEnum.MENU, "parent", ID_ROOT);
-        menuMapper.insert(parentMenuDO);
-        // 构建子菜单
-        MenuDO sonMenuDO = buildMenuDO(MenuTypeEnum.MENU, "testSonName",
-                parentMenuDO.getParentId());
-        menuMapper.insert(sonMenuDO);
-        return sonMenuDO;
-    }
-
-    private MenuDO buildMenuDO(MenuTypeEnum type, String name, Long parentId) {
-        return buildMenuDO(type, name, parentId, randomCommonStatus());
-    }
-
-    private MenuDO buildMenuDO(MenuTypeEnum type, String name, Long parentId, Integer status) {
-        return randomPojo(MenuDO.class, o -> o.setId(null).setName(name).setParentId(parentId)
-                .setType(type.getType()).setStatus(status));
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/permission/PermissionServiceTest.java b/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/permission/PermissionServiceTest.java
deleted file mode 100644
index bf41463..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/permission/PermissionServiceTest.java
+++ /dev/null
@@ -1,527 +0,0 @@
-package com.iailab.module.system.service.permission;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.extra.spring.SpringUtil;
-import com.iailab.framework.common.enums.CommonStatusEnum;
-import com.iailab.framework.test.core.ut.BaseDbUnitTest;
-import com.iailab.module.system.api.permission.dto.DeptDataPermissionRespDTO;
-import com.iailab.module.system.dal.dataobject.dept.DeptDO;
-import com.iailab.module.system.dal.dataobject.permission.MenuDO;
-import com.iailab.module.system.dal.dataobject.permission.RoleDO;
-import com.iailab.module.system.dal.dataobject.permission.RoleMenuDO;
-import com.iailab.module.system.dal.dataobject.permission.UserRoleDO;
-import com.iailab.module.system.dal.dataobject.user.AdminUserDO;
-import com.iailab.module.system.dal.mysql.permission.RoleMenuMapper;
-import com.iailab.module.system.dal.mysql.permission.UserRoleMapper;
-import com.iailab.module.system.enums.permission.DataScopeEnum;
-import com.iailab.module.system.service.dept.DeptService;
-import com.iailab.module.system.service.user.AdminUserService;
-import org.junit.jupiter.api.Test;
-import org.mockito.MockedStatic;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.context.annotation.Import;
-
-import javax.annotation.Resource;
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
-
-import static cn.hutool.core.collection.ListUtil.toList;
-import static com.iailab.framework.common.util.collection.SetUtils.asSet;
-import static com.iailab.framework.test.core.util.AssertUtils.assertPojoEquals;
-import static com.iailab.framework.test.core.util.RandomUtils.randomLongId;
-import static com.iailab.framework.test.core.util.RandomUtils.randomPojo;
-import static java.util.Collections.singleton;
-import static java.util.Collections.singletonList;
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.*;
-
-@Import({PermissionServiceImpl.class})
-public class PermissionServiceTest extends BaseDbUnitTest {
-
-    @Resource
-    private PermissionServiceImpl permissionService;
-
-    @Resource
-    private RoleMenuMapper roleMenuMapper;
-    @Resource
-    private UserRoleMapper userRoleMapper;
-
-    @MockBean
-    private RoleService roleService;
-    @MockBean
-    private MenuService menuService;
-    @MockBean
-    private DeptService deptService;
-    @MockBean
-    private AdminUserService userService;
-
-    @Test
-    public void testHasAnyPermissions_superAdmin() {
-        try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) {
-            springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(PermissionServiceImpl.class)))
-                    .thenReturn(permissionService);
-
-            // 准备参数
-            Long userId = 1L;
-            String[] roles = new String[]{"system:user:query", "system:user:create"};
-            // mock 用户登录的角色
-            userRoleMapper.insert(randomPojo(UserRoleDO.class).setUserId(userId).setRoleId(100L));
-            RoleDO role = randomPojo(RoleDO.class, o -> o.setId(100L)
-                    .setStatus(CommonStatusEnum.ENABLE.getStatus()));
-            when(roleService.getRoleListFromCache(eq(singleton(100L)))).thenReturn(toList(role));
-            // mock 其它方法
-            when(roleService.hasAnySuperAdmin(eq(asSet(100L)))).thenReturn(true);
-
-            // 调用,并断言
-            assertTrue(permissionService.hasAnyPermissions(userId, roles));
-        }
-    }
-
-    @Test
-    public void testHasAnyPermissions_normal() {
-        try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) {
-            springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(PermissionServiceImpl.class)))
-                    .thenReturn(permissionService);
-
-            // 准备参数
-            Long userId = 1L;
-            String[] roles = new String[]{"system:user:query", "system:user:create"};
-            // mock 用户登录的角色
-            userRoleMapper.insert(randomPojo(UserRoleDO.class).setUserId(userId).setRoleId(100L));
-            RoleDO role = randomPojo(RoleDO.class, o -> o.setId(100L)
-                    .setStatus(CommonStatusEnum.ENABLE.getStatus()));
-            when(roleService.getRoleListFromCache(eq(singleton(100L)))).thenReturn(toList(role));
-            // mock 菜单
-            Long menuId = 1000L;
-            when(menuService.getMenuIdListByPermissionFromCache(
-                    eq("system:user:create"))).thenReturn(singletonList(menuId));
-            roleMenuMapper.insert(randomPojo(RoleMenuDO.class).setRoleId(100L).setMenuId(1000L));
-
-            // 调用,并断言
-            assertTrue(permissionService.hasAnyPermissions(userId, roles));
-        }
-    }
-
-    @Test
-    public void testHasAnyRoles() {
-        try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) {
-            springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(PermissionServiceImpl.class)))
-                    .thenReturn(permissionService);
-
-            // 准备参数
-            Long userId = 1L;
-            String[] roles = new String[]{"yunai", "tudou"};
-            // mock 用户与角色的缓存
-            userRoleMapper.insert(randomPojo(UserRoleDO.class).setUserId(userId).setRoleId(100L));
-            RoleDO role = randomPojo(RoleDO.class, o -> o.setId(100L).setCode("tudou")
-                    .setStatus(CommonStatusEnum.ENABLE.getStatus()));
-            when(roleService.getRoleListFromCache(eq(singleton(100L)))).thenReturn(toList(role));
-
-            // 调用,并断言
-            assertTrue(permissionService.hasAnyRoles(userId, roles));
-        }
-    }
-
-    // ========== 角色-菜单的相关方法  ==========
-
-    @Test
-    public void testAssignRoleMenu() {
-        // 准备参数
-        Long roleId = 1L;
-        Set<Long> menuIds = asSet(200L, 300L);
-        // mock 数据
-        RoleMenuDO roleMenu01 = randomPojo(RoleMenuDO.class).setRoleId(1L).setMenuId(100L);
-        roleMenuMapper.insert(roleMenu01);
-        RoleMenuDO roleMenu02 = randomPojo(RoleMenuDO.class).setRoleId(1L).setMenuId(200L);
-        roleMenuMapper.insert(roleMenu02);
-
-        // 调用
-        permissionService.assignRoleMenu(roleId, menuIds);
-        // 断言
-        List<RoleMenuDO> roleMenuList = roleMenuMapper.selectList();
-        assertEquals(2, roleMenuList.size());
-        assertEquals(1L, roleMenuList.get(0).getRoleId());
-        assertEquals(200L, roleMenuList.get(0).getMenuId());
-        assertEquals(1L, roleMenuList.get(1).getRoleId());
-        assertEquals(300L, roleMenuList.get(1).getMenuId());
-    }
-
-    @Test
-    public void testProcessRoleDeleted() {
-        // 准备参数
-        Long roleId = randomLongId();
-        // mock 数据 UserRole
-        UserRoleDO userRoleDO01 = randomPojo(UserRoleDO.class, o -> o.setRoleId(roleId)); // 被删除
-        userRoleMapper.insert(userRoleDO01);
-        UserRoleDO userRoleDO02 = randomPojo(UserRoleDO.class); // 不被删除
-        userRoleMapper.insert(userRoleDO02);
-        // mock 数据 RoleMenu
-        RoleMenuDO roleMenuDO01 = randomPojo(RoleMenuDO.class, o -> o.setRoleId(roleId)); // 被删除
-        roleMenuMapper.insert(roleMenuDO01);
-        RoleMenuDO roleMenuDO02 = randomPojo(RoleMenuDO.class); // 不被删除
-        roleMenuMapper.insert(roleMenuDO02);
-
-        // 调用
-        permissionService.processRoleDeleted(roleId);
-        // 断言数据 RoleMenuDO
-        List<RoleMenuDO> dbRoleMenus = roleMenuMapper.selectList();
-        assertEquals(1, dbRoleMenus.size());
-        assertPojoEquals(dbRoleMenus.get(0), roleMenuDO02);
-        // 断言数据 UserRoleDO
-        List<UserRoleDO> dbUserRoles = userRoleMapper.selectList();
-        assertEquals(1, dbUserRoles.size());
-        assertPojoEquals(dbUserRoles.get(0), userRoleDO02);
-    }
-
-    @Test
-    public void testProcessMenuDeleted() {
-        // 准备参数
-        Long menuId = randomLongId();
-        // mock 数据
-        RoleMenuDO roleMenuDO01 = randomPojo(RoleMenuDO.class, o -> o.setMenuId(menuId)); // 被删除
-        roleMenuMapper.insert(roleMenuDO01);
-        RoleMenuDO roleMenuDO02 = randomPojo(RoleMenuDO.class); // 不被删除
-        roleMenuMapper.insert(roleMenuDO02);
-
-        // 调用
-        permissionService.processMenuDeleted(menuId);
-        // 断言数据
-        List<RoleMenuDO> dbRoleMenus = roleMenuMapper.selectList();
-        assertEquals(1, dbRoleMenus.size());
-        assertPojoEquals(dbRoleMenus.get(0), roleMenuDO02);
-    }
-
-    @Test
-    public void testGetRoleMenuIds_superAdmin() {
-        // 准备参数
-        Long roleId = 100L;
-        // mock 方法
-        when(roleService.hasAnySuperAdmin(eq(singleton(100L)))).thenReturn(true);
-        List<MenuDO> menuList = singletonList(randomPojo(MenuDO.class).setId(1L));
-        when(menuService.getMenuList()).thenReturn(menuList);
-
-        // 调用
-        Set<Long> menuIds = permissionService.getRoleMenuListByRoleId(roleId);
-        // 断言
-        assertEquals(singleton(1L), menuIds);
-    }
-
-    @Test
-    public void testGetRoleMenuIds_normal() {
-        // 准备参数
-        Long roleId = 100L;
-        // mock 数据
-        RoleMenuDO roleMenu01 = randomPojo(RoleMenuDO.class).setRoleId(100L).setMenuId(1L);
-        roleMenuMapper.insert(roleMenu01);
-        RoleMenuDO roleMenu02 = randomPojo(RoleMenuDO.class).setRoleId(100L).setMenuId(2L);
-        roleMenuMapper.insert(roleMenu02);
-
-        // 调用
-        Set<Long> menuIds = permissionService.getRoleMenuListByRoleId(roleId);
-        // 断言
-        assertEquals(asSet(1L, 2L), menuIds);
-    }
-
-    @Test
-    public void testGetMenuRoleIdListByMenuIdFromCache() {
-        // 准备参数
-        Long menuId = 1L;
-        // mock 数据
-        RoleMenuDO roleMenu01 = randomPojo(RoleMenuDO.class).setRoleId(100L).setMenuId(1L);
-        roleMenuMapper.insert(roleMenu01);
-        RoleMenuDO roleMenu02 = randomPojo(RoleMenuDO.class).setRoleId(200L).setMenuId(1L);
-        roleMenuMapper.insert(roleMenu02);
-
-        // 调用
-        Set<Long> roleIds = permissionService.getMenuRoleIdListByMenuIdFromCache(menuId);
-        // 断言
-        assertEquals(asSet(100L, 200L), roleIds);
-    }
-
-    // ========== 用户-角色的相关方法  ==========
-
-    @Test
-    public void testAssignUserRole() {
-        // 准备参数
-        Long userId = 1L;
-        Set<Long> roleIds = asSet(200L, 300L);
-        // mock 数据
-        UserRoleDO userRole01 = randomPojo(UserRoleDO.class).setUserId(1L).setRoleId(100L);
-        userRoleMapper.insert(userRole01);
-        UserRoleDO userRole02 = randomPojo(UserRoleDO.class).setUserId(1L).setRoleId(200L);
-        userRoleMapper.insert(userRole02);
-
-        // 调用
-        permissionService.assignUserRole(userId, roleIds);
-        // 断言
-        List<UserRoleDO> userRoleDOList = userRoleMapper.selectList();
-        assertEquals(2, userRoleDOList.size());
-        assertEquals(1L, userRoleDOList.get(0).getUserId());
-        assertEquals(200L, userRoleDOList.get(0).getRoleId());
-        assertEquals(1L, userRoleDOList.get(1).getUserId());
-        assertEquals(300L, userRoleDOList.get(1).getRoleId());
-    }
-
-    @Test
-    public void testProcessUserDeleted() {
-        // 准备参数
-        Long userId = randomLongId();
-        // mock 数据
-        UserRoleDO userRoleDO01 = randomPojo(UserRoleDO.class, o -> o.setUserId(userId)); // 被删除
-        userRoleMapper.insert(userRoleDO01);
-        UserRoleDO userRoleDO02 = randomPojo(UserRoleDO.class); // 不被删除
-        userRoleMapper.insert(userRoleDO02);
-
-        // 调用
-        permissionService.processUserDeleted(userId);
-        // 断言数据
-        List<UserRoleDO> dbUserRoles = userRoleMapper.selectList();
-        assertEquals(1, dbUserRoles.size());
-        assertPojoEquals(dbUserRoles.get(0), userRoleDO02);
-    }
-
-    @Test
-    public void testGetUserRoleIdListByUserId() {
-        // 准备参数
-        Long userId = 1L;
-        // mock 数据
-        UserRoleDO userRoleDO01 = randomPojo(UserRoleDO.class, o -> o.setUserId(1L).setRoleId(10L));
-        userRoleMapper.insert(userRoleDO01);
-        UserRoleDO roleMenuDO02 = randomPojo(UserRoleDO.class, o -> o.setUserId(1L).setRoleId(20L));
-        userRoleMapper.insert(roleMenuDO02);
-
-        // 调用
-        Set<Long> result = permissionService.getUserRoleIdListByUserId(userId);
-        // 断言
-        assertEquals(asSet(10L, 20L), result);
-    }
-
-    @Test
-    public void testGetUserRoleIdListByUserIdFromCache() {
-        // 准备参数
-        Long userId = 1L;
-        // mock 数据
-        UserRoleDO userRoleDO01 = randomPojo(UserRoleDO.class, o -> o.setUserId(1L).setRoleId(10L));
-        userRoleMapper.insert(userRoleDO01);
-        UserRoleDO roleMenuDO02 = randomPojo(UserRoleDO.class, o -> o.setUserId(1L).setRoleId(20L));
-        userRoleMapper.insert(roleMenuDO02);
-
-        // 调用
-        Set<Long> result = permissionService.getUserRoleIdListByUserIdFromCache(userId);
-        // 断言
-        assertEquals(asSet(10L, 20L), result);
-    }
-
-    @Test
-    public void testGetUserRoleIdsFromCache() {
-        // 准备参数
-        Long userId = 1L;
-        // mock 数据
-        UserRoleDO userRoleDO01 = randomPojo(UserRoleDO.class, o -> o.setUserId(1L).setRoleId(10L));
-        userRoleMapper.insert(userRoleDO01);
-        UserRoleDO roleMenuDO02 = randomPojo(UserRoleDO.class, o -> o.setUserId(1L).setRoleId(20L));
-        userRoleMapper.insert(roleMenuDO02);
-
-        // 调用
-        Set<Long> result = permissionService.getUserRoleIdListByUserIdFromCache(userId);
-        // 断言
-        assertEquals(asSet(10L, 20L), result);
-    }
-
-    @Test
-    public void testGetUserRoleIdListByRoleId() {
-        // 准备参数
-        Collection<Long> roleIds = asSet(10L, 20L);
-        // mock 数据
-        UserRoleDO userRoleDO01 = randomPojo(UserRoleDO.class, o -> o.setUserId(1L).setRoleId(10L));
-        userRoleMapper.insert(userRoleDO01);
-        UserRoleDO roleMenuDO02 = randomPojo(UserRoleDO.class, o -> o.setUserId(2L).setRoleId(20L));
-        userRoleMapper.insert(roleMenuDO02);
-
-        // 调用
-        Set<Long> result = permissionService.getUserRoleIdListByRoleId(roleIds);
-        // 断言
-        assertEquals(asSet(1L, 2L), result);
-    }
-
-    @Test
-    public void testGetEnableUserRoleListByUserIdFromCache() {
-        try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) {
-            springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(PermissionServiceImpl.class)))
-                    .thenReturn(permissionService);
-
-            // 准备参数
-            Long userId = 1L;
-            // mock 用户登录的角色
-            userRoleMapper.insert(randomPojo(UserRoleDO.class).setUserId(userId).setRoleId(100L));
-            userRoleMapper.insert(randomPojo(UserRoleDO.class).setUserId(userId).setRoleId(200L));
-            RoleDO role01 = randomPojo(RoleDO.class, o -> o.setId(100L)
-                    .setStatus(CommonStatusEnum.ENABLE.getStatus()));
-            RoleDO role02 = randomPojo(RoleDO.class, o -> o.setId(200L)
-                    .setStatus(CommonStatusEnum.DISABLE.getStatus()));
-            when(roleService.getRoleListFromCache(eq(asSet(100L, 200L))))
-                    .thenReturn(toList(role01, role02));
-
-            // 调用
-            List<RoleDO> result = permissionService.getEnableUserRoleListByUserIdFromCache(userId);
-            // 断言
-            assertEquals(1, result.size());
-            assertPojoEquals(role01, result.get(0));
-        }
-    }
-
-    // ========== 用户-部门的相关方法  ==========
-
-    @Test
-    public void testAssignRoleDataScope() {
-        // 准备参数
-        Long roleId = 1L;
-        Integer dataScope = 2;
-        Set<Long> dataScopeDeptIds = asSet(10L, 20L);
-
-        // 调用
-        permissionService.assignRoleDataScope(roleId, dataScope, dataScopeDeptIds);
-        // 断言
-        verify(roleService).updateRoleDataScope(eq(roleId), eq(dataScope), eq(dataScopeDeptIds));
-    }
-
-    @Test
-    public void testGetDeptDataPermission_All() {
-        try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) {
-            springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(PermissionServiceImpl.class)))
-                    .thenReturn(permissionService);
-
-            // 准备参数
-            Long userId = 1L;
-            // mock 用户的角色编号
-            userRoleMapper.insert(randomPojo(UserRoleDO.class).setUserId(userId).setRoleId(2L));
-            // mock 获得用户的角色
-            RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.ALL.getScope())
-                    .setStatus(CommonStatusEnum.ENABLE.getStatus()));
-            when(roleService.getRoleListFromCache(eq(singleton(2L)))).thenReturn(toList(roleDO));
-
-            // 调用
-            DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(userId);
-            // 断言
-            assertTrue(result.getAll());
-            assertFalse(result.getSelf());
-            assertTrue(CollUtil.isEmpty(result.getDeptIds()));
-        }
-    }
-
-    @Test
-    public void testGetDeptDataPermission_DeptCustom() {
-        try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) {
-            springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(PermissionServiceImpl.class)))
-                    .thenReturn(permissionService);
-
-            // 准备参数
-            Long userId = 1L;
-            // mock 用户的角色编号
-            userRoleMapper.insert(randomPojo(UserRoleDO.class).setUserId(userId).setRoleId(2L));
-            // mock 获得用户的角色
-            RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.DEPT_CUSTOM.getScope())
-                    .setStatus(CommonStatusEnum.ENABLE.getStatus()));
-            when(roleService.getRoleListFromCache(eq(singleton(2L)))).thenReturn(toList(roleDO));
-            // mock 部门的返回
-            when(userService.getUser(eq(1L))).thenReturn(new AdminUserDO().setDeptId(3L),
-                    null, null); // 最后返回 null 的目的,看看会不会重复调用
-
-            // 调用
-            DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(userId);
-            // 断言
-            assertFalse(result.getAll());
-            assertFalse(result.getSelf());
-            assertEquals(roleDO.getDataScopeDeptIds().size() + 1, result.getDeptIds().size());
-            assertTrue(CollUtil.containsAll(result.getDeptIds(), roleDO.getDataScopeDeptIds()));
-            assertTrue(CollUtil.contains(result.getDeptIds(), 3L));
-        }
-    }
-
-    @Test
-    public void testGetDeptDataPermission_DeptOnly() {
-        try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) {
-            springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(PermissionServiceImpl.class)))
-                    .thenReturn(permissionService);
-
-            // 准备参数
-            Long userId = 1L;
-            // mock 用户的角色编号
-            userRoleMapper.insert(randomPojo(UserRoleDO.class).setUserId(userId).setRoleId(2L));
-            // mock 获得用户的角色
-            RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.DEPT_ONLY.getScope())
-                    .setStatus(CommonStatusEnum.ENABLE.getStatus()));
-            when(roleService.getRoleListFromCache(eq(singleton(2L)))).thenReturn(toList(roleDO));
-            // mock 部门的返回
-            when(userService.getUser(eq(1L))).thenReturn(new AdminUserDO().setDeptId(3L),
-                    null, null); // 最后返回 null 的目的,看看会不会重复调用
-
-            // 调用
-            DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(userId);
-            // 断言
-            assertFalse(result.getAll());
-            assertFalse(result.getSelf());
-            assertEquals(1, result.getDeptIds().size());
-            assertTrue(CollUtil.contains(result.getDeptIds(), 3L));
-        }
-    }
-
-    @Test
-    public void testGetDeptDataPermission_DeptAndChild() {
-        try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) {
-            springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(PermissionServiceImpl.class)))
-                    .thenReturn(permissionService);
-
-            // 准备参数
-            Long userId = 1L;
-            // mock 用户的角色编号
-            userRoleMapper.insert(randomPojo(UserRoleDO.class).setUserId(userId).setRoleId(2L));
-            // mock 获得用户的角色
-            RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.DEPT_AND_CHILD.getScope())
-                    .setStatus(CommonStatusEnum.ENABLE.getStatus()));
-            when(roleService.getRoleListFromCache(eq(singleton(2L)))).thenReturn(toList(roleDO));
-            // mock 部门的返回
-            when(userService.getUser(eq(1L))).thenReturn(new AdminUserDO().setDeptId(3L),
-                    null, null); // 最后返回 null 的目的,看看会不会重复调用
-            // mock 方法(部门)
-            DeptDO deptDO = randomPojo(DeptDO.class);
-            when(deptService.getChildDeptIdListFromCache(eq(3L))).thenReturn(singleton(deptDO.getId()));
-
-            // 调用
-            DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(userId);
-            // 断言
-            assertFalse(result.getAll());
-            assertFalse(result.getSelf());
-            assertEquals(2, result.getDeptIds().size());
-            assertTrue(CollUtil.contains(result.getDeptIds(), deptDO.getId()));
-            assertTrue(CollUtil.contains(result.getDeptIds(), 3L));
-        }
-    }
-
-    @Test
-    public void testGetDeptDataPermission_Self() {
-        try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) {
-            springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(PermissionServiceImpl.class)))
-                    .thenReturn(permissionService);
-
-            // 准备参数
-            Long userId = 1L;
-            // mock 用户的角色编号
-            userRoleMapper.insert(randomPojo(UserRoleDO.class).setUserId(userId).setRoleId(2L));
-            // mock 获得用户的角色
-            RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.SELF.getScope())
-                    .setStatus(CommonStatusEnum.ENABLE.getStatus()));
-            when(roleService.getRoleListFromCache(eq(singleton(2L)))).thenReturn(toList(roleDO));
-
-            // 调用
-            DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(userId);
-            // 断言
-            assertFalse(result.getAll());
-            assertTrue(result.getSelf());
-            assertTrue(CollUtil.isEmpty(result.getDeptIds()));
-        }
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/permission/RoleServiceImplTest.java b/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/permission/RoleServiceImplTest.java
deleted file mode 100644
index 006c8c3..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/permission/RoleServiceImplTest.java
+++ /dev/null
@@ -1,371 +0,0 @@
-package com.iailab.module.system.service.permission;
-
-import cn.hutool.extra.spring.SpringUtil;
-import com.iailab.framework.common.enums.CommonStatusEnum;
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.framework.test.core.ut.BaseDbUnitTest;
-import com.iailab.module.system.controller.admin.permission.vo.role.RolePageReqVO;
-import com.iailab.module.system.controller.admin.permission.vo.role.RoleSaveReqVO;
-import com.iailab.module.system.dal.dataobject.permission.RoleDO;
-import com.iailab.module.system.dal.mysql.permission.RoleMapper;
-import com.iailab.module.system.enums.permission.DataScopeEnum;
-import com.iailab.module.system.enums.permission.RoleTypeEnum;
-import org.junit.jupiter.api.Test;
-import org.mockito.MockedStatic;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.context.annotation.Import;
-
-import javax.annotation.Resource;
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
-
-import static cn.hutool.core.util.RandomUtil.randomEle;
-import static com.iailab.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
-import static com.iailab.framework.common.util.date.LocalDateTimeUtils.buildTime;
-import static com.iailab.framework.common.util.object.ObjectUtils.cloneIgnoreId;
-import static com.iailab.framework.test.core.util.AssertUtils.assertPojoEquals;
-import static com.iailab.framework.test.core.util.AssertUtils.assertServiceException;
-import static com.iailab.framework.test.core.util.RandomUtils.*;
-import static com.iailab.module.system.enums.ErrorCodeConstants.*;
-import static java.util.Collections.singleton;
-import static java.util.Collections.singletonList;
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mockStatic;
-import static org.mockito.Mockito.verify;
-
-@Import(RoleServiceImpl.class)
-public class RoleServiceImplTest extends BaseDbUnitTest {
-
-    @Resource
-    private RoleServiceImpl roleService;
-
-    @Resource
-    private RoleMapper roleMapper;
-
-    @MockBean
-    private PermissionService permissionService;
-
-    @Test
-    public void testCreateRole() {
-        // 准备参数
-        RoleSaveReqVO reqVO = randomPojo(RoleSaveReqVO.class)
-                .setId(null); // 防止 id 被赋值
-
-        // 调用
-        Long roleId = roleService.createRole(reqVO, null);
-        // 断言
-        RoleDO roleDO = roleMapper.selectById(roleId);
-        assertPojoEquals(reqVO, roleDO, "id");
-        assertEquals(RoleTypeEnum.CUSTOM.getType(), roleDO.getType());
-        assertEquals(CommonStatusEnum.ENABLE.getStatus(), roleDO.getStatus());
-        assertEquals(DataScopeEnum.ALL.getScope(), roleDO.getDataScope());
-    }
-
-    @Test
-    public void testUpdateRole() {
-        // mock 数据
-        RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setType(RoleTypeEnum.CUSTOM.getType()));
-        roleMapper.insert(roleDO);
-        // 准备参数
-        Long id = roleDO.getId();
-        RoleSaveReqVO reqVO = randomPojo(RoleSaveReqVO.class, o -> o.setId(id));
-
-        // 调用
-        roleService.updateRole(reqVO);
-        // 断言
-        RoleDO newRoleDO = roleMapper.selectById(id);
-        assertPojoEquals(reqVO, newRoleDO);
-    }
-
-    @Test
-    public void testUpdateRoleDataScope() {
-        // mock 数据
-        RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setType(RoleTypeEnum.CUSTOM.getType()));
-        roleMapper.insert(roleDO);
-        // 准备参数
-        Long id = roleDO.getId();
-        Integer dataScope = randomEle(DataScopeEnum.values()).getScope();
-        Set<Long> dataScopeRoleIds = randomSet(Long.class);
-
-        // 调用
-        roleService.updateRoleDataScope(id, dataScope, dataScopeRoleIds);
-        // 断言
-        RoleDO dbRoleDO = roleMapper.selectById(id);
-        assertEquals(dataScope, dbRoleDO.getDataScope());
-        assertEquals(dataScopeRoleIds, dbRoleDO.getDataScopeDeptIds());
-    }
-
-    @Test
-    public void testDeleteRole() {
-        // mock 数据
-        RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setType(RoleTypeEnum.CUSTOM.getType()));
-        roleMapper.insert(roleDO);
-        // 参数准备
-        Long id = roleDO.getId();
-
-        // 调用
-        roleService.deleteRole(id);
-        // 断言
-        assertNull(roleMapper.selectById(id));
-        // verify 删除相关数据
-        verify(permissionService).processRoleDeleted(id);
-    }
-
-    @Test
-    public void testValidateRoleDuplicate_success() {
-        // 调用,不会抛异常
-        roleService.validateRoleDuplicate(randomString(), randomString(), null);
-    }
-
-    @Test
-    public void testValidateRoleDuplicate_nameDuplicate() {
-        // mock 数据
-        RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setName("role_name"));
-        roleMapper.insert(roleDO);
-        // 准备参数
-        String name = "role_name";
-
-        // 调用,并断言异常
-        assertServiceException(() -> roleService.validateRoleDuplicate(name, randomString(), null),
-                ROLE_NAME_DUPLICATE, name);
-    }
-
-    @Test
-    public void testValidateRoleDuplicate_codeDuplicate() {
-        // mock 数据
-        RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setCode("code"));
-        roleMapper.insert(roleDO);
-        // 准备参数
-        String code = "code";
-
-        // 调用,并断言异常
-        assertServiceException(() -> roleService.validateRoleDuplicate(randomString(), code, null),
-                ROLE_CODE_DUPLICATE, code);
-    }
-
-    @Test
-    public void testValidateUpdateRole_success() {
-        RoleDO roleDO = randomPojo(RoleDO.class);
-        roleMapper.insert(roleDO);
-        // 准备参数
-        Long id = roleDO.getId();
-
-        // 调用,无异常
-        roleService.validateRoleForUpdate(id);
-    }
-
-    @Test
-    public void testValidateUpdateRole_roleIdNotExist() {
-        assertServiceException(() -> roleService.validateRoleForUpdate(randomLongId()), ROLE_NOT_EXISTS);
-    }
-
-    @Test
-    public void testValidateUpdateRole_systemRoleCanNotBeUpdate() {
-        RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setType(RoleTypeEnum.SYSTEM.getType()));
-        roleMapper.insert(roleDO);
-        // 准备参数
-        Long id = roleDO.getId();
-
-        assertServiceException(() -> roleService.validateRoleForUpdate(id),
-                ROLE_CAN_NOT_UPDATE_SYSTEM_TYPE_ROLE);
-    }
-
-    @Test
-    public void testGetRole() {
-        // mock 数据
-        RoleDO roleDO = randomPojo(RoleDO.class);
-        roleMapper.insert(roleDO);
-        // 参数准备
-        Long id = roleDO.getId();
-
-        // 调用
-        RoleDO dbRoleDO = roleService.getRole(id);
-        // 断言
-        assertPojoEquals(roleDO, dbRoleDO);
-    }
-
-    @Test
-    public void testGetRoleFromCache() {
-        // mock 数据(缓存)
-        RoleDO roleDO = randomPojo(RoleDO.class);
-        roleMapper.insert(roleDO);
-        // 参数准备
-        Long id = roleDO.getId();
-
-        // 调用
-        RoleDO dbRoleDO = roleService.getRoleFromCache(id);
-        // 断言
-        assertPojoEquals(roleDO, dbRoleDO);
-    }
-
-    @Test
-    public void testGetRoleListByStatus() {
-        // mock 数据
-        RoleDO dbRole01 = randomPojo(RoleDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus()));
-        roleMapper.insert(dbRole01);
-        RoleDO dbRole02 = randomPojo(RoleDO.class, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()));
-        roleMapper.insert(dbRole02);
-
-        // 调用
-        List<RoleDO> list = roleService.getRoleListByStatus(
-                singleton(CommonStatusEnum.ENABLE.getStatus()));
-        // 断言
-        assertEquals(1, list.size());
-        assertPojoEquals(dbRole01, list.get(0));
-    }
-
-    @Test
-    public void testGetRoleList() {
-        // mock 数据
-        RoleDO dbRole01 = randomPojo(RoleDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus()));
-        roleMapper.insert(dbRole01);
-        RoleDO dbRole02 = randomPojo(RoleDO.class, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()));
-        roleMapper.insert(dbRole02);
-
-        // 调用
-        List<RoleDO> list = roleService.getRoleList();
-        // 断言
-        assertEquals(2, list.size());
-        assertPojoEquals(dbRole01, list.get(0));
-        assertPojoEquals(dbRole02, list.get(1));
-    }
-
-    @Test
-    public void testGetRoleList_ids() {
-        // mock 数据
-        RoleDO dbRole01 = randomPojo(RoleDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus()));
-        roleMapper.insert(dbRole01);
-        RoleDO dbRole02 = randomPojo(RoleDO.class, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()));
-        roleMapper.insert(dbRole02);
-        // 准备参数
-        Collection<Long> ids = singleton(dbRole01.getId());
-
-        // 调用
-        List<RoleDO> list = roleService.getRoleList(ids);
-        // 断言
-        assertEquals(1, list.size());
-        assertPojoEquals(dbRole01, list.get(0));
-    }
-
-    @Test
-    public void testGetRoleListFromCache() {
-        try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) {
-            springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(RoleServiceImpl.class)))
-                    .thenReturn(roleService);
-
-            // mock 数据
-            RoleDO dbRole = randomPojo(RoleDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus()));
-            roleMapper.insert(dbRole);
-            // 测试 id 不匹配
-            roleMapper.insert(cloneIgnoreId(dbRole, o -> {}));
-            // 准备参数
-            Collection<Long> ids = singleton(dbRole.getId());
-
-            // 调用
-            List<RoleDO> list = roleService.getRoleListFromCache(ids);
-            // 断言
-            assertEquals(1, list.size());
-            assertPojoEquals(dbRole, list.get(0));
-        }
-    }
-
-    @Test
-    public void testGetRolePage() {
-        // mock 数据
-        RoleDO dbRole = randomPojo(RoleDO.class, o -> { // 等会查询到
-            o.setName("土豆");
-            o.setCode("tudou");
-            o.setStatus(CommonStatusEnum.ENABLE.getStatus());
-            o.setCreateTime(buildTime(2022, 2, 8));
-        });
-        roleMapper.insert(dbRole);
-        // 测试 name 不匹配
-        roleMapper.insert(cloneIgnoreId(dbRole, o -> o.setName("红薯")));
-        // 测试 code 不匹配
-        roleMapper.insert(cloneIgnoreId(dbRole, o -> o.setCode("hong")));
-        // 测试 createTime 不匹配
-        roleMapper.insert(cloneIgnoreId(dbRole, o -> o.setCreateTime(buildTime(2022, 2, 16))));
-        // 准备参数
-        RolePageReqVO reqVO = new RolePageReqVO();
-        reqVO.setName("土豆");
-        reqVO.setCode("tu");
-        reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
-        reqVO.setCreateTime(buildBetweenTime(2022, 2, 1, 2022, 2, 12));
-
-        // 调用
-        PageResult<RoleDO> pageResult = roleService.getRolePage(reqVO);
-        // 断言
-        assertEquals(1, pageResult.getTotal());
-        assertEquals(1, pageResult.getList().size());
-        assertPojoEquals(dbRole, pageResult.getList().get(0));
-    }
-
-    @Test
-    public void testHasAnySuperAdmin_true() {
-        try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) {
-            springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(RoleServiceImpl.class)))
-                    .thenReturn(roleService);
-
-            // mock 数据
-            RoleDO dbRole = randomPojo(RoleDO.class).setCode("super_admin");
-            roleMapper.insert(dbRole);
-            // 准备参数
-            Long id = dbRole.getId();
-
-            // 调用,并调用
-            assertTrue(roleService.hasAnySuperAdmin(singletonList(id)));
-        }
-    }
-
-    @Test
-    public void testHasAnySuperAdmin_false() {
-        try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) {
-            springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(RoleServiceImpl.class)))
-                    .thenReturn(roleService);
-
-            // mock 数据
-            RoleDO dbRole = randomPojo(RoleDO.class).setCode("tenant_admin");
-            roleMapper.insert(dbRole);
-            // 准备参数
-            Long id = dbRole.getId();
-
-            // 调用,并调用
-            assertFalse(roleService.hasAnySuperAdmin(singletonList(id)));
-        }
-    }
-
-    @Test
-    public void testValidateRoleList_success() {
-        // mock 数据
-        RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus()));
-        roleMapper.insert(roleDO);
-        // 准备参数
-        List<Long> ids = singletonList(roleDO.getId());
-
-        // 调用,无需断言
-        roleService.validateRoleList(ids);
-    }
-
-    @Test
-    public void testValidateRoleList_notFound() {
-        // 准备参数
-        List<Long> ids = singletonList(randomLongId());
-
-        // 调用, 并断言异常
-        assertServiceException(() -> roleService.validateRoleList(ids), ROLE_NOT_EXISTS);
-    }
-
-    @Test
-    public void testValidateRoleList_notEnable() {
-        // mock 数据
-        RoleDO RoleDO = randomPojo(RoleDO.class, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()));
-        roleMapper.insert(RoleDO);
-        // 准备参数
-        List<Long> ids = singletonList(RoleDO.getId());
-
-        // 调用, 并断言异常
-        assertServiceException(() -> roleService.validateRoleList(ids), ROLE_IS_DISABLE, RoleDO.getName());
-    }
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/sms/SmsChannelServiceTest.java b/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/sms/SmsChannelServiceTest.java
deleted file mode 100644
index 552cb9d..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/sms/SmsChannelServiceTest.java
+++ /dev/null
@@ -1,236 +0,0 @@
-package com.iailab.module.system.service.sms;
-
-import com.iailab.framework.common.enums.CommonStatusEnum;
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.framework.common.util.object.BeanUtils;
-import com.iailab.module.system.framework.sms.core.client.SmsClient;
-import com.iailab.module.system.framework.sms.core.client.SmsClientFactory;
-import com.iailab.module.system.framework.sms.core.property.SmsChannelProperties;
-import com.iailab.framework.test.core.ut.BaseDbUnitTest;
-import com.iailab.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO;
-import com.iailab.module.system.controller.admin.sms.vo.channel.SmsChannelSaveReqVO;
-import com.iailab.module.system.dal.dataobject.sms.SmsChannelDO;
-import com.iailab.module.system.dal.mysql.sms.SmsChannelMapper;
-import org.junit.jupiter.api.Test;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.context.annotation.Import;
-
-import javax.annotation.Resource;
-import java.util.List;
-
-import static com.iailab.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
-import static com.iailab.framework.common.util.date.LocalDateTimeUtils.buildTime;
-import static com.iailab.framework.common.util.object.ObjectUtils.cloneIgnoreId;
-import static com.iailab.framework.test.core.util.AssertUtils.assertPojoEquals;
-import static com.iailab.framework.test.core.util.AssertUtils.assertServiceException;
-import static com.iailab.framework.test.core.util.RandomUtils.*;
-import static com.iailab.module.system.enums.ErrorCodeConstants.SMS_CHANNEL_HAS_CHILDREN;
-import static com.iailab.module.system.enums.ErrorCodeConstants.SMS_CHANNEL_NOT_EXISTS;
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.*;
-
-@Import(SmsChannelServiceImpl.class)
-public class SmsChannelServiceTest extends BaseDbUnitTest {
-
-    @Resource
-    private SmsChannelServiceImpl smsChannelService;
-
-    @Resource
-    private SmsChannelMapper smsChannelMapper;
-
-    @MockBean
-    private SmsClientFactory smsClientFactory;
-    @MockBean
-    private SmsTemplateService smsTemplateService;
-
-    @Test
-    public void testCreateSmsChannel_success() {
-        // 准备参数
-        SmsChannelSaveReqVO reqVO = randomPojo(SmsChannelSaveReqVO.class, o -> o.setStatus(randomCommonStatus()))
-                .setId(null); // 防止 id 被赋值
-
-        // 调用
-        Long smsChannelId = smsChannelService.createSmsChannel(reqVO);
-        // 断言
-        assertNotNull(smsChannelId);
-        // 校验记录的属性是否正确
-        SmsChannelDO smsChannel = smsChannelMapper.selectById(smsChannelId);
-        assertPojoEquals(reqVO, smsChannel, "id");
-        // 断言 cache
-        assertNull(smsChannelService.getIdClientCache().getIfPresent(smsChannel.getId()));
-        assertNull(smsChannelService.getCodeClientCache().getIfPresent(smsChannel.getCode()));
-    }
-
-    @Test
-    public void testUpdateSmsChannel_success() {
-        // mock 数据
-        SmsChannelDO dbSmsChannel = randomPojo(SmsChannelDO.class);
-        smsChannelMapper.insert(dbSmsChannel);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        SmsChannelSaveReqVO reqVO = randomPojo(SmsChannelSaveReqVO.class, o -> {
-            o.setId(dbSmsChannel.getId()); // 设置更新的 ID
-            o.setStatus(randomCommonStatus());
-            o.setCallbackUrl(randomString());
-        });
-
-        // 调用
-        smsChannelService.updateSmsChannel(reqVO);
-        // 校验是否更新正确
-        SmsChannelDO smsChannel = smsChannelMapper.selectById(reqVO.getId()); // 获取最新的
-        assertPojoEquals(reqVO, smsChannel);
-        // 断言 cache
-        assertNull(smsChannelService.getIdClientCache().getIfPresent(smsChannel.getId()));
-        assertNull(smsChannelService.getCodeClientCache().getIfPresent(smsChannel.getCode()));
-    }
-
-    @Test
-    public void testUpdateSmsChannel_notExists() {
-        // 准备参数
-        SmsChannelSaveReqVO reqVO = randomPojo(SmsChannelSaveReqVO.class);
-
-        // 调用, 并断言异常
-        assertServiceException(() -> smsChannelService.updateSmsChannel(reqVO), SMS_CHANNEL_NOT_EXISTS);
-    }
-
-    @Test
-    public void testDeleteSmsChannel_success() {
-        // mock 数据
-        SmsChannelDO dbSmsChannel = randomPojo(SmsChannelDO.class);
-        smsChannelMapper.insert(dbSmsChannel);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        Long id = dbSmsChannel.getId();
-
-        // 调用
-        smsChannelService.deleteSmsChannel(id);
-        // 校验数据不存在了
-        assertNull(smsChannelMapper.selectById(id));
-        // 断言 cache
-        assertNull(smsChannelService.getIdClientCache().getIfPresent(dbSmsChannel.getId()));
-        assertNull(smsChannelService.getCodeClientCache().getIfPresent(dbSmsChannel.getCode()));
-    }
-
-    @Test
-    public void testDeleteSmsChannel_notExists() {
-        // 准备参数
-        Long id = randomLongId();
-
-        // 调用, 并断言异常
-        assertServiceException(() -> smsChannelService.deleteSmsChannel(id), SMS_CHANNEL_NOT_EXISTS);
-    }
-
-    @Test
-    public void testDeleteSmsChannel_hasChildren() {
-        // mock 数据
-        SmsChannelDO dbSmsChannel = randomPojo(SmsChannelDO.class);
-        smsChannelMapper.insert(dbSmsChannel);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        Long id = dbSmsChannel.getId();
-        // mock 方法
-        when(smsTemplateService.getSmsTemplateCountByChannelId(eq(id))).thenReturn(10L);
-
-        // 调用, 并断言异常
-        assertServiceException(() -> smsChannelService.deleteSmsChannel(id), SMS_CHANNEL_HAS_CHILDREN);
-    }
-
-    @Test
-    public void testGetSmsChannel() {
-        // mock 数据
-        SmsChannelDO dbSmsChannel = randomPojo(SmsChannelDO.class);
-        smsChannelMapper.insert(dbSmsChannel); // @Sql: 先插入出一条存在的数据
-        // 准备参数
-        Long id = dbSmsChannel.getId();
-
-        // 调用,并断言
-        assertPojoEquals(dbSmsChannel, smsChannelService.getSmsChannel(id));
-    }
-
-    @Test
-    public void testGetSmsChannelList() {
-        // mock 数据
-        SmsChannelDO dbSmsChannel01 = randomPojo(SmsChannelDO.class);
-        smsChannelMapper.insert(dbSmsChannel01);
-        SmsChannelDO dbSmsChannel02 = randomPojo(SmsChannelDO.class);
-        smsChannelMapper.insert(dbSmsChannel02);
-        // 准备参数
-
-        // 调用
-        List<SmsChannelDO> list = smsChannelService.getSmsChannelList();
-        // 断言
-        assertEquals(2, list.size());
-        assertPojoEquals(dbSmsChannel01, list.get(0));
-        assertPojoEquals(dbSmsChannel02, list.get(1));
-    }
-
-    @Test
-    public void testGetSmsChannelPage() {
-       // mock 数据
-       SmsChannelDO dbSmsChannel = randomPojo(SmsChannelDO.class, o -> { // 等会查询到
-           o.setSignature("iailab");
-           o.setStatus(CommonStatusEnum.ENABLE.getStatus());
-           o.setCreateTime(buildTime(2020, 12, 12));
-       });
-       smsChannelMapper.insert(dbSmsChannel);
-       // 测试 signature 不匹配
-       smsChannelMapper.insert(cloneIgnoreId(dbSmsChannel, o -> o.setSignature("源码")));
-       // 测试 status 不匹配
-       smsChannelMapper.insert(cloneIgnoreId(dbSmsChannel, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
-       // 测试 createTime 不匹配
-       smsChannelMapper.insert(cloneIgnoreId(dbSmsChannel, o -> o.setCreateTime(buildTime(2020, 11, 11))));
-       // 准备参数
-       SmsChannelPageReqVO reqVO = new SmsChannelPageReqVO();
-       reqVO.setSignature("平台");
-       reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
-       reqVO.setCreateTime(buildBetweenTime(2020, 12, 1, 2020, 12, 24));
-
-       // 调用
-       PageResult<SmsChannelDO> pageResult = smsChannelService.getSmsChannelPage(reqVO);
-       // 断言
-       assertEquals(1, pageResult.getTotal());
-       assertEquals(1, pageResult.getList().size());
-       assertPojoEquals(dbSmsChannel, pageResult.getList().get(0));
-    }
-
-    @Test
-    public void testGetSmsClient_id() {
-        // mock 数据
-        SmsChannelDO channel = randomPojo(SmsChannelDO.class);
-        smsChannelMapper.insert(channel);
-        // mock 参数
-        Long id = channel.getId();
-        // mock 方法
-        SmsClient mockClient = mock(SmsClient.class);
-        when(smsClientFactory.getSmsClient(eq(id))).thenReturn(mockClient);
-
-        // 调用
-        SmsClient client = smsChannelService.getSmsClient(id);
-        // 断言
-        assertSame(client, mockClient);
-        verify(smsClientFactory).createOrUpdateSmsClient(argThat(arg -> {
-            SmsChannelProperties properties = BeanUtils.toBean(channel, SmsChannelProperties.class);
-            return properties.equals(arg);
-        }));
-    }
-
-    @Test
-    public void testGetSmsClient_code() {
-        // mock 数据
-        SmsChannelDO channel = randomPojo(SmsChannelDO.class);
-        smsChannelMapper.insert(channel);
-        // mock 参数
-        String code = channel.getCode();
-        // mock 方法
-        SmsClient mockClient = mock(SmsClient.class);
-        when(smsClientFactory.getSmsClient(eq(code))).thenReturn(mockClient);
-
-        // 调用
-        SmsClient client = smsChannelService.getSmsClient(code);
-        // 断言
-        assertSame(client, mockClient);
-        verify(smsClientFactory).createOrUpdateSmsClient(argThat(arg -> {
-            SmsChannelProperties properties = BeanUtils.toBean(channel, SmsChannelProperties.class);
-            return properties.equals(arg);
-        }));
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/sms/SmsCodeServiceImplTest.java b/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/sms/SmsCodeServiceImplTest.java
deleted file mode 100644
index fdc2d21..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/sms/SmsCodeServiceImplTest.java
+++ /dev/null
@@ -1,209 +0,0 @@
-package com.iailab.module.system.service.sms;
-
-import cn.hutool.core.map.MapUtil;
-import com.iailab.framework.mybatis.core.enums.SqlConstants;
-import com.iailab.framework.test.core.ut.BaseDbUnitTest;
-import com.iailab.module.system.api.sms.dto.code.SmsCodeSendReqDTO;
-import com.iailab.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
-import com.iailab.module.system.api.sms.dto.code.SmsCodeValidateReqDTO;
-import com.iailab.module.system.dal.dataobject.sms.SmsCodeDO;
-import com.iailab.module.system.dal.mysql.sms.SmsCodeMapper;
-import com.iailab.module.system.enums.sms.SmsSceneEnum;
-import com.iailab.module.system.framework.sms.config.SmsCodeProperties;
-import com.baomidou.mybatisplus.annotation.DbType;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.context.annotation.Import;
-
-import javax.annotation.Resource;
-import java.time.Duration;
-import java.time.LocalDateTime;
-
-import static cn.hutool.core.util.RandomUtil.randomEle;
-import static com.iailab.framework.test.core.util.AssertUtils.assertPojoEquals;
-import static com.iailab.framework.test.core.util.AssertUtils.assertServiceException;
-import static com.iailab.framework.test.core.util.RandomUtils.randomPojo;
-import static com.iailab.module.system.enums.ErrorCodeConstants.*;
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.ArgumentMatchers.isNull;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-@Import(SmsCodeServiceImpl.class)
-public class SmsCodeServiceImplTest extends BaseDbUnitTest {
-
-    @Resource
-    private SmsCodeServiceImpl smsCodeService;
-
-    @Resource
-    private SmsCodeMapper smsCodeMapper;
-
-    @MockBean
-    private SmsCodeProperties smsCodeProperties;
-    @MockBean
-    private SmsSendService smsSendService;
-
-    @BeforeEach
-    public void setUp() {
-        when(smsCodeProperties.getExpireTimes()).thenReturn(Duration.ofMinutes(5));
-        when(smsCodeProperties.getSendFrequency()).thenReturn(Duration.ofMinutes(1));
-        when(smsCodeProperties.getSendMaximumQuantityPerDay()).thenReturn(10);
-        when(smsCodeProperties.getBeginCode()).thenReturn(9999);
-        when(smsCodeProperties.getEndCode()).thenReturn(9999);
-    }
-
-    @Test
-    public void sendSmsCode_success() {
-        // 准备参数
-        SmsCodeSendReqDTO reqDTO = randomPojo(SmsCodeSendReqDTO.class, o -> {
-            o.setMobile("15601691300");
-            o.setScene(SmsSceneEnum.MEMBER_LOGIN.getScene());
-        });
-        // mock 方法
-        SqlConstants.init(DbType.MYSQL);
-
-        // 调用
-        smsCodeService.sendSmsCode(reqDTO);
-        // 断言 code 验证码
-        SmsCodeDO smsCodeDO = smsCodeMapper.selectOne(null);
-        assertPojoEquals(reqDTO, smsCodeDO);
-        assertEquals("9999", smsCodeDO.getCode());
-        assertEquals(1, smsCodeDO.getTodayIndex());
-        assertFalse(smsCodeDO.getUsed());
-        // 断言调用
-        verify(smsSendService).sendSingleSms(eq(reqDTO.getMobile()), isNull(), isNull(),
-                eq("user-sms-login"), eq(MapUtil.of("code", "9999")));
-    }
-
-    @Test
-    public void sendSmsCode_tooFast() {
-        // mock 数据
-        SmsCodeDO smsCodeDO = randomPojo(SmsCodeDO.class,
-                o -> o.setMobile("15601691300").setTodayIndex(1));
-        smsCodeMapper.insert(smsCodeDO);
-        // 准备参数
-        SmsCodeSendReqDTO reqDTO = randomPojo(SmsCodeSendReqDTO.class, o -> {
-            o.setMobile("15601691300");
-            o.setScene(SmsSceneEnum.MEMBER_LOGIN.getScene());
-        });
-        // mock 方法
-        SqlConstants.init(DbType.MYSQL);
-
-        // 调用,并断言异常
-        assertServiceException(() -> smsCodeService.sendSmsCode(reqDTO),
-                SMS_CODE_SEND_TOO_FAST);
-    }
-
-    @Test
-    public void sendSmsCode_exceedDay() {
-        // mock 数据
-        SmsCodeDO smsCodeDO = randomPojo(SmsCodeDO.class,
-                o -> o.setMobile("15601691300").setTodayIndex(10).setCreateTime(LocalDateTime.now()));
-        smsCodeMapper.insert(smsCodeDO);
-        // 准备参数
-        SmsCodeSendReqDTO reqDTO = randomPojo(SmsCodeSendReqDTO.class, o -> {
-            o.setMobile("15601691300");
-            o.setScene(SmsSceneEnum.MEMBER_LOGIN.getScene());
-        });
-        // mock 方法
-        SqlConstants.init(DbType.MYSQL);
-        when(smsCodeProperties.getSendFrequency()).thenReturn(Duration.ofMillis(0));
-
-        // 调用,并断言异常
-        assertServiceException(() -> smsCodeService.sendSmsCode(reqDTO),
-                SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY);
-    }
-
-    @Test
-    public void testUseSmsCode_success() {
-        // 准备参数
-        SmsCodeUseReqDTO reqDTO = randomPojo(SmsCodeUseReqDTO.class, o -> {
-            o.setMobile("15601691300");
-            o.setScene(randomEle(SmsSceneEnum.values()).getScene());
-        });
-        // mock 数据
-        SqlConstants.init(DbType.MYSQL);
-        smsCodeMapper.insert(randomPojo(SmsCodeDO.class, o -> {
-            o.setMobile(reqDTO.getMobile()).setScene(reqDTO.getScene())
-                    .setCode(reqDTO.getCode()).setUsed(false);
-        }));
-
-        // 调用
-        smsCodeService.useSmsCode(reqDTO);
-        // 断言
-        SmsCodeDO smsCodeDO = smsCodeMapper.selectOne(null);
-        assertTrue(smsCodeDO.getUsed());
-        assertNotNull(smsCodeDO.getUsedTime());
-        assertEquals(reqDTO.getUsedIp(), smsCodeDO.getUsedIp());
-    }
-
-    @Test
-    public void validateSmsCode_success() {
-        // 准备参数
-        SmsCodeValidateReqDTO reqDTO = randomPojo(SmsCodeValidateReqDTO.class, o -> {
-            o.setMobile("15601691300");
-            o.setScene(randomEle(SmsSceneEnum.values()).getScene());
-        });
-        // mock 数据
-        SqlConstants.init(DbType.MYSQL);
-        smsCodeMapper.insert(randomPojo(SmsCodeDO.class, o -> o.setMobile(reqDTO.getMobile())
-                .setScene(reqDTO.getScene()).setCode(reqDTO.getCode()).setUsed(false)));
-
-        // 调用
-        smsCodeService.validateSmsCode(reqDTO);
-    }
-
-    @Test
-    public void validateSmsCode_notFound() {
-        // 准备参数
-        SmsCodeValidateReqDTO reqDTO = randomPojo(SmsCodeValidateReqDTO.class, o -> {
-            o.setMobile("15601691300");
-            o.setScene(randomEle(SmsSceneEnum.values()).getScene());
-        });
-        // mock 数据
-        SqlConstants.init(DbType.MYSQL);
-
-        // 调用,并断言异常
-        assertServiceException(() -> smsCodeService.validateSmsCode(reqDTO),
-                SMS_CODE_NOT_FOUND);
-    }
-
-    @Test
-    public void validateSmsCode_expired() {
-        // 准备参数
-        SmsCodeValidateReqDTO reqDTO = randomPojo(SmsCodeValidateReqDTO.class, o -> {
-            o.setMobile("15601691300");
-            o.setScene(randomEle(SmsSceneEnum.values()).getScene());
-        });
-        // mock 数据
-        SqlConstants.init(DbType.MYSQL);
-        smsCodeMapper.insert(randomPojo(SmsCodeDO.class, o -> o.setMobile(reqDTO.getMobile())
-                .setScene(reqDTO.getScene()).setCode(reqDTO.getCode()).setUsed(false)
-                .setCreateTime(LocalDateTime.now().minusMinutes(6))));
-
-        // 调用,并断言异常
-        assertServiceException(() -> smsCodeService.validateSmsCode(reqDTO),
-                SMS_CODE_EXPIRED);
-    }
-
-    @Test
-    public void validateSmsCode_used() {
-        // 准备参数
-        SmsCodeValidateReqDTO reqDTO = randomPojo(SmsCodeValidateReqDTO.class, o -> {
-            o.setMobile("15601691300");
-            o.setScene(randomEle(SmsSceneEnum.values()).getScene());
-        });
-        // mock 数据
-        SqlConstants.init(DbType.MYSQL);
-        smsCodeMapper.insert(randomPojo(SmsCodeDO.class, o -> o.setMobile(reqDTO.getMobile())
-                .setScene(reqDTO.getScene()).setCode(reqDTO.getCode()).setUsed(true)
-                .setCreateTime(LocalDateTime.now())));
-
-        // 调用,并断言异常
-        assertServiceException(() -> smsCodeService.validateSmsCode(reqDTO),
-                SMS_CODE_USED);
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/sms/SmsLogServiceImplTest.java b/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/sms/SmsLogServiceImplTest.java
deleted file mode 100644
index b1fbc97..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/sms/SmsLogServiceImplTest.java
+++ /dev/null
@@ -1,190 +0,0 @@
-package com.iailab.module.system.service.sms;
-
-import cn.hutool.core.map.MapUtil;
-import com.iailab.framework.common.enums.UserTypeEnum;
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.framework.common.util.collection.ArrayUtils;
-import com.iailab.framework.test.core.ut.BaseDbUnitTest;
-import com.iailab.module.system.controller.admin.sms.vo.log.SmsLogPageReqVO;
-import com.iailab.module.system.dal.dataobject.sms.SmsLogDO;
-import com.iailab.module.system.dal.dataobject.sms.SmsTemplateDO;
-import com.iailab.module.system.dal.mysql.sms.SmsLogMapper;
-import com.iailab.module.system.enums.sms.SmsReceiveStatusEnum;
-import com.iailab.module.system.enums.sms.SmsSendStatusEnum;
-import com.iailab.module.system.enums.sms.SmsTemplateTypeEnum;
-import org.junit.jupiter.api.Test;
-import org.springframework.context.annotation.Import;
-
-import javax.annotation.Resource;
-import java.time.LocalDateTime;
-import java.util.Map;
-import java.util.function.Consumer;
-
-import static cn.hutool.core.util.RandomUtil.randomBoolean;
-import static cn.hutool.core.util.RandomUtil.randomEle;
-import static com.iailab.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
-import static com.iailab.framework.common.util.date.LocalDateTimeUtils.buildTime;
-import static com.iailab.framework.common.util.object.ObjectUtils.cloneIgnoreId;
-import static com.iailab.framework.test.core.util.AssertUtils.assertPojoEquals;
-import static com.iailab.framework.test.core.util.RandomUtils.*;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-
-@Import(SmsLogServiceImpl.class)
-public class SmsLogServiceImplTest extends BaseDbUnitTest {
-
-    @Resource
-    private SmsLogServiceImpl smsLogService;
-
-    @Resource
-    private SmsLogMapper smsLogMapper;
-
-    @Test
-    public void testGetSmsLogPage() {
-       // mock 数据
-       SmsLogDO dbSmsLog = randomSmsLogDO(o -> { // 等会查询到
-           o.setChannelId(1L);
-           o.setTemplateId(10L);
-           o.setMobile("15601691300");
-           o.setSendStatus(SmsSendStatusEnum.INIT.getStatus());
-           o.setSendTime(buildTime(2020, 11, 11));
-           o.setReceiveStatus(SmsReceiveStatusEnum.INIT.getStatus());
-           o.setReceiveTime(buildTime(2021, 11, 11));
-       });
-       smsLogMapper.insert(dbSmsLog);
-       // 测试 channelId 不匹配
-       smsLogMapper.insert(cloneIgnoreId(dbSmsLog, o -> o.setChannelId(2L)));
-       // 测试 templateId 不匹配
-       smsLogMapper.insert(cloneIgnoreId(dbSmsLog, o -> o.setTemplateId(20L)));
-       // 测试 mobile 不匹配
-       smsLogMapper.insert(cloneIgnoreId(dbSmsLog, o -> o.setMobile("18818260999")));
-       // 测试 sendStatus 不匹配
-       smsLogMapper.insert(cloneIgnoreId(dbSmsLog, o -> o.setSendStatus(SmsSendStatusEnum.IGNORE.getStatus())));
-       // 测试 sendTime 不匹配
-       smsLogMapper.insert(cloneIgnoreId(dbSmsLog, o -> o.setSendTime(buildTime(2020, 12, 12))));
-       // 测试 receiveStatus 不匹配
-       smsLogMapper.insert(cloneIgnoreId(dbSmsLog, o -> o.setReceiveStatus(SmsReceiveStatusEnum.SUCCESS.getStatus())));
-       // 测试 receiveTime 不匹配
-       smsLogMapper.insert(cloneIgnoreId(dbSmsLog, o -> o.setReceiveTime(buildTime(2021, 12, 12))));
-       // 准备参数
-       SmsLogPageReqVO reqVO = new SmsLogPageReqVO();
-       reqVO.setChannelId(1L);
-       reqVO.setTemplateId(10L);
-       reqVO.setMobile("156");
-       reqVO.setSendStatus(SmsSendStatusEnum.INIT.getStatus());
-       reqVO.setSendTime(buildBetweenTime(2020, 11, 1, 2020, 11, 30));
-       reqVO.setReceiveStatus(SmsReceiveStatusEnum.INIT.getStatus());
-       reqVO.setReceiveTime(buildBetweenTime(2021, 11, 1, 2021, 11, 30));
-
-       // 调用
-       PageResult<SmsLogDO> pageResult = smsLogService.getSmsLogPage(reqVO);
-       // 断言
-       assertEquals(1, pageResult.getTotal());
-       assertEquals(1, pageResult.getList().size());
-       assertPojoEquals(dbSmsLog, pageResult.getList().get(0));
-    }
-
-    @Test
-    public void testCreateSmsLog() {
-        // 准备参数
-        String mobile = randomString();
-        Long userId = randomLongId();
-        Integer userType = randomEle(UserTypeEnum.values()).getValue();
-        Boolean isSend = randomBoolean();
-        SmsTemplateDO templateDO = randomPojo(SmsTemplateDO.class,
-                o -> o.setType(randomEle(SmsTemplateTypeEnum.values()).getType()));
-        String templateContent = randomString();
-        Map<String, Object> templateParams = randomTemplateParams();
-        // mock 方法
-
-        // 调用
-        Long logId = smsLogService.createSmsLog(mobile, userId, userType, isSend,
-                templateDO, templateContent, templateParams);
-        // 断言
-        SmsLogDO logDO = smsLogMapper.selectById(logId);
-        assertEquals(isSend ? SmsSendStatusEnum.INIT.getStatus() : SmsSendStatusEnum.IGNORE.getStatus(),
-                logDO.getSendStatus());
-        assertEquals(mobile, logDO.getMobile());
-        assertEquals(userType, logDO.getUserType());
-        assertEquals(userId, logDO.getUserId());
-        assertEquals(templateDO.getId(), logDO.getTemplateId());
-        assertEquals(templateDO.getCode(), logDO.getTemplateCode());
-        assertEquals(templateDO.getType(), logDO.getTemplateType());
-        assertEquals(templateDO.getChannelId(), logDO.getChannelId());
-        assertEquals(templateDO.getChannelCode(), logDO.getChannelCode());
-        assertEquals(templateContent, logDO.getTemplateContent());
-        assertEquals(templateParams, logDO.getTemplateParams());
-        assertEquals(SmsReceiveStatusEnum.INIT.getStatus(), logDO.getReceiveStatus());
-    }
-
-    @Test
-    public void testUpdateSmsSendResult() {
-        // mock 数据
-        SmsLogDO dbSmsLog = randomSmsLogDO(
-                o -> o.setSendStatus(SmsSendStatusEnum.IGNORE.getStatus()));
-        smsLogMapper.insert(dbSmsLog);
-        // 准备参数
-        Long id = dbSmsLog.getId();
-        Boolean success = randomBoolean();
-        String apiSendCode = randomString();
-        String apiSendMsg = randomString();
-        String apiRequestId = randomString();
-        String apiSerialNo = randomString();
-
-        // 调用
-        smsLogService.updateSmsSendResult(id, success,
-                apiSendCode, apiSendMsg, apiRequestId, apiSerialNo);
-        // 断言
-        dbSmsLog = smsLogMapper.selectById(id);
-        assertEquals(success ? SmsSendStatusEnum.SUCCESS.getStatus() : SmsSendStatusEnum.FAILURE.getStatus(),
-                dbSmsLog.getSendStatus());
-        assertNotNull(dbSmsLog.getSendTime());
-        assertEquals(apiSendCode, dbSmsLog.getApiSendCode());
-        assertEquals(apiSendMsg, dbSmsLog.getApiSendMsg());
-        assertEquals(apiRequestId, dbSmsLog.getApiRequestId());
-        assertEquals(apiSerialNo, dbSmsLog.getApiSerialNo());
-    }
-
-    @Test
-    public void testUpdateSmsReceiveResult() {
-        // mock 数据
-        SmsLogDO dbSmsLog = randomSmsLogDO(
-                o -> o.setReceiveStatus(SmsReceiveStatusEnum.INIT.getStatus()));
-        smsLogMapper.insert(dbSmsLog);
-        // 准备参数
-        Long id = dbSmsLog.getId();
-        Boolean success = randomBoolean();
-        LocalDateTime receiveTime = randomLocalDateTime();
-        String apiReceiveCode = randomString();
-        String apiReceiveMsg = randomString();
-
-        // 调用
-        smsLogService.updateSmsReceiveResult(id, success, receiveTime, apiReceiveCode, apiReceiveMsg);
-        // 断言
-        dbSmsLog = smsLogMapper.selectById(id);
-        assertEquals(success ? SmsReceiveStatusEnum.SUCCESS.getStatus()
-                : SmsReceiveStatusEnum.FAILURE.getStatus(), dbSmsLog.getReceiveStatus());
-        assertEquals(receiveTime, dbSmsLog.getReceiveTime());
-        assertEquals(apiReceiveCode, dbSmsLog.getApiReceiveCode());
-        assertEquals(apiReceiveMsg, dbSmsLog.getApiReceiveMsg());
-    }
-
-    // ========== 随机对象 ==========
-
-    @SafeVarargs
-    private static SmsLogDO randomSmsLogDO(Consumer<SmsLogDO>... consumers) {
-        Consumer<SmsLogDO> consumer = (o) -> {
-            o.setTemplateParams(randomTemplateParams());
-            o.setTemplateType(randomEle(SmsTemplateTypeEnum.values()).getType()); // 保证 templateType 的范围
-            o.setUserType(randomEle(UserTypeEnum.values()).getValue()); // 保证 userType 的范围
-            o.setSendStatus(randomEle(SmsSendStatusEnum.values()).getStatus()); // 保证 sendStatus 的范围
-            o.setReceiveStatus(randomEle(SmsReceiveStatusEnum.values()).getStatus()); // 保证 receiveStatus 的范围
-        };
-        return randomPojo(SmsLogDO.class, ArrayUtils.append(consumer, consumers));
-    }
-
-    private static Map<String, Object> randomTemplateParams() {
-        return MapUtil.<String, Object>builder().put(randomString(), randomString())
-                .put(randomString(), randomString()).build();
-    }
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/sms/SmsSendServiceImplTest.java b/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/sms/SmsSendServiceImplTest.java
deleted file mode 100644
index 4666508..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/sms/SmsSendServiceImplTest.java
+++ /dev/null
@@ -1,298 +0,0 @@
-package com.iailab.module.system.service.sms;
-
-import cn.hutool.core.map.MapUtil;
-import com.iailab.framework.common.core.KeyValue;
-import com.iailab.framework.common.enums.CommonStatusEnum;
-import com.iailab.framework.common.enums.UserTypeEnum;
-import com.iailab.module.system.framework.sms.core.client.SmsClient;
-import com.iailab.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO;
-import com.iailab.module.system.framework.sms.core.client.dto.SmsSendRespDTO;
-import com.iailab.framework.test.core.ut.BaseMockitoUnitTest;
-import com.iailab.module.system.dal.dataobject.sms.SmsChannelDO;
-import com.iailab.module.system.dal.dataobject.sms.SmsTemplateDO;
-import com.iailab.module.system.dal.dataobject.user.AdminUserDO;
-import com.iailab.module.system.mq.message.sms.SmsSendMessage;
-import com.iailab.module.system.mq.producer.sms.SmsProducer;
-import com.iailab.module.system.service.member.MemberService;
-import com.iailab.module.system.service.user.AdminUserService;
-import org.assertj.core.util.Lists;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import static cn.hutool.core.util.RandomUtil.randomEle;
-import static com.iailab.framework.test.core.util.AssertUtils.assertServiceException;
-import static com.iailab.framework.test.core.util.RandomUtils.*;
-import static com.iailab.module.system.enums.ErrorCodeConstants.*;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.*;
-
-public class SmsSendServiceImplTest extends BaseMockitoUnitTest {
-
-    @InjectMocks
-    private SmsSendServiceImpl smsSendService;
-
-    @Mock
-    private AdminUserService adminUserService;
-    @Mock
-    private MemberService memberService;
-    @Mock
-    private SmsChannelService smsChannelService;
-    @Mock
-    private SmsTemplateService smsTemplateService;
-    @Mock
-    private SmsLogService smsLogService;
-    @Mock
-    private SmsProducer smsProducer;
-
-    @Test
-    public void testSendSingleSmsToAdmin() {
-        // 准备参数
-        Long userId = randomLongId();
-        String templateCode = randomString();
-        Map<String, Object> templateParams = MapUtil.<String, Object>builder().put("code", "1234")
-                .put("op", "login").build();
-        // mock adminUserService 的方法
-        AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setMobile("15601691300"));
-        when(adminUserService.getUser(eq(userId))).thenReturn(user);
-
-        // mock SmsTemplateService 的方法
-        SmsTemplateDO template = randomPojo(SmsTemplateDO.class, o -> {
-            o.setStatus(CommonStatusEnum.ENABLE.getStatus());
-            o.setContent("验证码为{code}, 操作为{op}");
-            o.setParams(Lists.newArrayList("code", "op"));
-        });
-        when(smsTemplateService.getSmsTemplateByCodeFromCache(eq(templateCode))).thenReturn(template);
-        String content = randomString();
-        when(smsTemplateService.formatSmsTemplateContent(eq(template.getContent()), eq(templateParams)))
-                .thenReturn(content);
-        // mock SmsChannelService 的方法
-        SmsChannelDO smsChannel = randomPojo(SmsChannelDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus()));
-        when(smsChannelService.getSmsChannel(eq(template.getChannelId()))).thenReturn(smsChannel);
-        // mock SmsLogService 的方法
-        Long smsLogId = randomLongId();
-        when(smsLogService.createSmsLog(eq(user.getMobile()), eq(userId), eq(UserTypeEnum.ADMIN.getValue()), eq(Boolean.TRUE), eq(template),
-                eq(content), eq(templateParams))).thenReturn(smsLogId);
-
-        // 调用
-        Long resultSmsLogId = smsSendService.sendSingleSmsToAdmin(null, userId, templateCode, templateParams);
-        // 断言
-        assertEquals(smsLogId, resultSmsLogId);
-        // 断言调用
-        verify(smsProducer).sendSmsSendMessage(eq(smsLogId), eq(user.getMobile()),
-                eq(template.getChannelId()), eq(template.getApiTemplateId()),
-                eq(Lists.newArrayList(new KeyValue<>("code", "1234"), new KeyValue<>("op", "login"))));
-    }
-
-    @Test
-    public void testSendSingleSmsToUser() {
-        // 准备参数
-        Long userId = randomLongId();
-        String templateCode = randomString();
-        Map<String, Object> templateParams = MapUtil.<String, Object>builder().put("code", "1234")
-                .put("op", "login").build();
-        // mock memberService 的方法
-        String mobile = "15601691300";
-        when(memberService.getMemberUserMobile(eq(userId))).thenReturn(mobile);
-
-        // mock SmsTemplateService 的方法
-        SmsTemplateDO template = randomPojo(SmsTemplateDO.class, o -> {
-            o.setStatus(CommonStatusEnum.ENABLE.getStatus());
-            o.setContent("验证码为{code}, 操作为{op}");
-            o.setParams(Lists.newArrayList("code", "op"));
-        });
-        when(smsTemplateService.getSmsTemplateByCodeFromCache(eq(templateCode))).thenReturn(template);
-        String content = randomString();
-        when(smsTemplateService.formatSmsTemplateContent(eq(template.getContent()), eq(templateParams)))
-                .thenReturn(content);
-        // mock SmsChannelService 的方法
-        SmsChannelDO smsChannel = randomPojo(SmsChannelDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus()));
-        when(smsChannelService.getSmsChannel(eq(template.getChannelId()))).thenReturn(smsChannel);
-        // mock SmsLogService 的方法
-        Long smsLogId = randomLongId();
-        when(smsLogService.createSmsLog(eq(mobile), eq(userId), eq(UserTypeEnum.MEMBER.getValue()), eq(Boolean.TRUE), eq(template),
-                eq(content), eq(templateParams))).thenReturn(smsLogId);
-
-        // 调用
-        Long resultSmsLogId = smsSendService.sendSingleSmsToMember(null, userId, templateCode, templateParams);
-        // 断言
-        assertEquals(smsLogId, resultSmsLogId);
-        // 断言调用
-        verify(smsProducer).sendSmsSendMessage(eq(smsLogId), eq(mobile),
-                eq(template.getChannelId()), eq(template.getApiTemplateId()),
-                eq(Lists.newArrayList(new KeyValue<>("code", "1234"), new KeyValue<>("op", "login"))));
-    }
-
-    /**
-     * 发送成功,当短信模板开启时
-     */
-    @Test
-    public void testSendSingleSms_successWhenSmsTemplateEnable() {
-        // 准备参数
-        String mobile = randomString();
-        Long userId = randomLongId();
-        Integer userType = randomEle(UserTypeEnum.values()).getValue();
-        String templateCode = randomString();
-        Map<String, Object> templateParams = MapUtil.<String, Object>builder().put("code", "1234")
-                .put("op", "login").build();
-        // mock SmsTemplateService 的方法
-        SmsTemplateDO template = randomPojo(SmsTemplateDO.class, o -> {
-            o.setStatus(CommonStatusEnum.ENABLE.getStatus());
-            o.setContent("验证码为{code}, 操作为{op}");
-            o.setParams(Lists.newArrayList("code", "op"));
-        });
-        when(smsTemplateService.getSmsTemplateByCodeFromCache(eq(templateCode))).thenReturn(template);
-        String content = randomString();
-        when(smsTemplateService.formatSmsTemplateContent(eq(template.getContent()), eq(templateParams)))
-                .thenReturn(content);
-        // mock SmsChannelService 的方法
-        SmsChannelDO smsChannel = randomPojo(SmsChannelDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus()));
-        when(smsChannelService.getSmsChannel(eq(template.getChannelId()))).thenReturn(smsChannel);
-        // mock SmsLogService 的方法
-        Long smsLogId = randomLongId();
-        when(smsLogService.createSmsLog(eq(mobile), eq(userId), eq(userType), eq(Boolean.TRUE), eq(template),
-                eq(content), eq(templateParams))).thenReturn(smsLogId);
-
-        // 调用
-        Long resultSmsLogId = smsSendService.sendSingleSms(mobile, userId, userType, templateCode, templateParams);
-        // 断言
-        assertEquals(smsLogId, resultSmsLogId);
-        // 断言调用
-        verify(smsProducer).sendSmsSendMessage(eq(smsLogId), eq(mobile),
-                eq(template.getChannelId()), eq(template.getApiTemplateId()),
-                eq(Lists.newArrayList(new KeyValue<>("code", "1234"), new KeyValue<>("op", "login"))));
-    }
-
-    /**
-     * 发送成功,当短信模板关闭时
-     */
-    @Test
-    public void testSendSingleSms_successWhenSmsTemplateDisable() {
-        // 准备参数
-        String mobile = randomString();
-        Long userId = randomLongId();
-        Integer userType = randomEle(UserTypeEnum.values()).getValue();
-        String templateCode = randomString();
-        Map<String, Object> templateParams = MapUtil.<String, Object>builder().put("code", "1234")
-                .put("op", "login").build();
-        // mock SmsTemplateService 的方法
-        SmsTemplateDO template = randomPojo(SmsTemplateDO.class, o -> {
-            o.setStatus(CommonStatusEnum.DISABLE.getStatus());
-            o.setContent("验证码为{code}, 操作为{op}");
-            o.setParams(Lists.newArrayList("code", "op"));
-        });
-        when(smsTemplateService.getSmsTemplateByCodeFromCache(eq(templateCode))).thenReturn(template);
-        String content = randomString();
-        when(smsTemplateService.formatSmsTemplateContent(eq(template.getContent()), eq(templateParams)))
-                .thenReturn(content);
-        // mock SmsChannelService 的方法
-        SmsChannelDO smsChannel = randomPojo(SmsChannelDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus()));
-        when(smsChannelService.getSmsChannel(eq(template.getChannelId()))).thenReturn(smsChannel);
-        // mock SmsLogService 的方法
-        Long smsLogId = randomLongId();
-        when(smsLogService.createSmsLog(eq(mobile), eq(userId), eq(userType), eq(Boolean.FALSE), eq(template),
-                eq(content), eq(templateParams))).thenReturn(smsLogId);
-
-        // 调用
-        Long resultSmsLogId = smsSendService.sendSingleSms(mobile, userId, userType, templateCode, templateParams);
-        // 断言
-        assertEquals(smsLogId, resultSmsLogId);
-        // 断言调用
-        verify(smsProducer, times(0)).sendSmsSendMessage(anyLong(), anyString(),
-                anyLong(), any(), anyList());
-    }
-
-    @Test
-    public void testCheckSmsTemplateValid_notExists() {
-        // 准备参数
-        String templateCode = randomString();
-        // mock 方法
-
-        // 调用,并断言异常
-        assertServiceException(() -> smsSendService.validateSmsTemplate(templateCode),
-                SMS_SEND_TEMPLATE_NOT_EXISTS);
-    }
-
-    @Test
-    public void testBuildTemplateParams_paramMiss() {
-        // 准备参数
-        SmsTemplateDO template = randomPojo(SmsTemplateDO.class,
-                o -> o.setParams(Lists.newArrayList("code")));
-        Map<String, Object> templateParams = new HashMap<>();
-        // mock 方法
-
-        // 调用,并断言异常
-        assertServiceException(() -> smsSendService.buildTemplateParams(template, templateParams),
-                SMS_SEND_MOBILE_TEMPLATE_PARAM_MISS, "code");
-    }
-
-    @Test
-    public void testCheckMobile_notExists() {
-        // 准备参数
-        // mock 方法
-
-        // 调用,并断言异常
-        assertServiceException(() -> smsSendService.validateMobile(null),
-                SMS_SEND_MOBILE_NOT_EXISTS);
-    }
-
-    @Test
-    public void testSendBatchNotify() {
-        // 准备参数
-        // mock 方法
-
-        // 调用
-        UnsupportedOperationException exception = Assertions.assertThrows(
-                UnsupportedOperationException.class,
-                () -> smsSendService.sendBatchSms(null, null, null, null, null)
-        );
-        // 断言
-        assertEquals("暂时不支持该操作,感兴趣可以实现该功能哟!", exception.getMessage());
-    }
-
-    @Test
-    @SuppressWarnings("unchecked")
-    public void testDoSendSms() throws Throwable {
-        // 准备参数
-        SmsSendMessage message = randomPojo(SmsSendMessage.class);
-        // mock SmsClientFactory 的方法
-        SmsClient smsClient = spy(SmsClient.class);
-        when(smsChannelService.getSmsClient(eq(message.getChannelId()))).thenReturn(smsClient);
-        // mock SmsClient 的方法
-        SmsSendRespDTO sendResult = randomPojo(SmsSendRespDTO.class);
-        when(smsClient.sendSms(eq(message.getLogId()), eq(message.getMobile()), eq(message.getApiTemplateId()),
-                eq(message.getTemplateParams()))).thenReturn(sendResult);
-
-        // 调用
-        smsSendService.doSendSms(message);
-        // 断言
-        verify(smsLogService).updateSmsSendResult(eq(message.getLogId()),
-                eq(sendResult.getSuccess()), eq(sendResult.getApiCode()),
-                eq(sendResult.getApiMsg()), eq(sendResult.getApiRequestId()), eq(sendResult.getSerialNo()));
-    }
-
-    @Test
-    public void testReceiveSmsStatus() throws Throwable {
-        // 准备参数
-        String channelCode = randomString();
-        String text = randomString();
-        // mock SmsClientFactory 的方法
-        SmsClient smsClient = spy(SmsClient.class);
-        when(smsChannelService.getSmsClient(eq(channelCode))).thenReturn(smsClient);
-        // mock SmsClient 的方法
-        List<SmsReceiveRespDTO> receiveResults = randomPojoList(SmsReceiveRespDTO.class);
-
-        // 调用
-        smsSendService.receiveSmsStatus(channelCode, text);
-        // 断言
-        receiveResults.forEach(result -> smsLogService.updateSmsReceiveResult(eq(result.getLogId()), eq(result.getSuccess()),
-                eq(result.getReceiveTime()), eq(result.getErrorCode()), eq(result.getErrorCode())));
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/sms/SmsTemplateServiceImplTest.java b/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/sms/SmsTemplateServiceImplTest.java
deleted file mode 100644
index 769cf42..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/sms/SmsTemplateServiceImplTest.java
+++ /dev/null
@@ -1,348 +0,0 @@
-package com.iailab.module.system.service.sms;
-
-import cn.hutool.core.map.MapUtil;
-import com.iailab.framework.common.enums.CommonStatusEnum;
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.framework.common.util.collection.ArrayUtils;
-import com.iailab.framework.common.util.object.ObjectUtils;
-import com.iailab.module.system.framework.sms.core.client.SmsClient;
-import com.iailab.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO;
-import com.iailab.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
-import com.iailab.framework.test.core.ut.BaseDbUnitTest;
-import com.iailab.module.system.controller.admin.sms.vo.template.SmsTemplatePageReqVO;
-import com.iailab.module.system.controller.admin.sms.vo.template.SmsTemplateSaveReqVO;
-import com.iailab.module.system.dal.dataobject.sms.SmsChannelDO;
-import com.iailab.module.system.dal.dataobject.sms.SmsTemplateDO;
-import com.iailab.module.system.dal.mysql.sms.SmsTemplateMapper;
-import com.iailab.module.system.enums.sms.SmsTemplateTypeEnum;
-import com.google.common.collect.Lists;
-import org.junit.jupiter.api.Test;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.context.annotation.Import;
-
-import javax.annotation.Resource;
-import java.util.List;
-import java.util.Map;
-import java.util.function.Consumer;
-
-import static cn.hutool.core.util.RandomUtil.randomEle;
-import static com.iailab.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
-import static com.iailab.framework.common.util.date.LocalDateTimeUtils.buildTime;
-import static com.iailab.framework.test.core.util.AssertUtils.assertPojoEquals;
-import static com.iailab.framework.test.core.util.AssertUtils.assertServiceException;
-import static com.iailab.framework.test.core.util.RandomUtils.*;
-import static com.iailab.module.system.enums.ErrorCodeConstants.*;
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.when;
-
-@Import(SmsTemplateServiceImpl.class)
-public class SmsTemplateServiceImplTest extends BaseDbUnitTest {
-
-    @Resource
-    private SmsTemplateServiceImpl smsTemplateService;
-
-    @Resource
-    private SmsTemplateMapper smsTemplateMapper;
-
-    @MockBean
-    private SmsChannelService smsChannelService;
-    @MockBean
-    private SmsClient smsClient;
-
-    @Test
-    public void testFormatSmsTemplateContent() {
-        // 准备参数
-        String content = "正在进行登录操作{operation},您的验证码是{code}";
-        Map<String, Object> params = MapUtil.<String, Object>builder("operation", "登录")
-                .put("code", "1234").build();
-
-        // 调用
-        String result = smsTemplateService.formatSmsTemplateContent(content, params);
-        // 断言
-        assertEquals("正在进行登录操作登录,您的验证码是1234", result);
-    }
-
-    @Test
-    public void testParseTemplateContentParams() {
-        // 准备参数
-        String content = "正在进行登录操作{operation},您的验证码是{code}";
-        // mock 方法
-
-        // 调用
-        List<String> params = smsTemplateService.parseTemplateContentParams(content);
-        // 断言
-        assertEquals(Lists.newArrayList("operation", "code"), params);
-    }
-
-    @Test
-    @SuppressWarnings("unchecked")
-    public void testCreateSmsTemplate_success() throws Throwable {
-        // 准备参数
-        SmsTemplateSaveReqVO reqVO = randomPojo(SmsTemplateSaveReqVO.class, o -> {
-            o.setContent("正在进行登录操作{operation},您的验证码是{code}");
-            o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围
-            o.setType(randomEle(SmsTemplateTypeEnum.values()).getType()); // 保证 type 的 范围
-        }).setId(null); // 防止 id 被赋值
-        // mock Channel 的方法
-        SmsChannelDO channelDO = randomPojo(SmsChannelDO.class, o -> {
-            o.setId(reqVO.getChannelId());
-            o.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 保证 status 开启,创建必须处于这个状态
-        });
-        when(smsChannelService.getSmsChannel(eq(channelDO.getId()))).thenReturn(channelDO);
-        // mock 获得 API 短信模板成功
-        when(smsChannelService.getSmsClient(eq(reqVO.getChannelId()))).thenReturn(smsClient);
-        when(smsClient.getSmsTemplate(eq(reqVO.getApiTemplateId()))).thenReturn(
-                randomPojo(SmsTemplateRespDTO.class, o -> o.setAuditStatus(SmsTemplateAuditStatusEnum.SUCCESS.getStatus())));
-
-        // 调用
-        Long smsTemplateId = smsTemplateService.createSmsTemplate(reqVO);
-        // 断言
-        assertNotNull(smsTemplateId);
-        // 校验记录的属性是否正确
-        SmsTemplateDO smsTemplate = smsTemplateMapper.selectById(smsTemplateId);
-        assertPojoEquals(reqVO, smsTemplate, "id");
-        assertEquals(Lists.newArrayList("operation", "code"), smsTemplate.getParams());
-        assertEquals(channelDO.getCode(), smsTemplate.getChannelCode());
-    }
-
-    @Test
-    @SuppressWarnings("unchecked")
-    public void testUpdateSmsTemplate_success() throws Throwable {
-        // mock 数据
-        SmsTemplateDO dbSmsTemplate = randomSmsTemplateDO();
-        smsTemplateMapper.insert(dbSmsTemplate);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        SmsTemplateSaveReqVO reqVO = randomPojo(SmsTemplateSaveReqVO.class, o -> {
-            o.setId(dbSmsTemplate.getId()); // 设置更新的 ID
-            o.setContent("正在进行登录操作{operation},您的验证码是{code}");
-            o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围
-            o.setType(randomEle(SmsTemplateTypeEnum.values()).getType()); // 保证 type 的 范围
-        });
-        // mock 方法
-        SmsChannelDO channelDO = randomPojo(SmsChannelDO.class, o -> {
-            o.setId(reqVO.getChannelId());
-            o.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 保证 status 开启,创建必须处于这个状态
-        });
-        when(smsChannelService.getSmsChannel(eq(channelDO.getId()))).thenReturn(channelDO);
-        // mock 获得 API 短信模板成功
-        when(smsChannelService.getSmsClient(eq(reqVO.getChannelId()))).thenReturn(smsClient);
-        when(smsClient.getSmsTemplate(eq(reqVO.getApiTemplateId()))).thenReturn(
-                randomPojo(SmsTemplateRespDTO.class, o -> o.setAuditStatus(SmsTemplateAuditStatusEnum.SUCCESS.getStatus())));
-
-        // 调用
-        smsTemplateService.updateSmsTemplate(reqVO);
-        // 校验是否更新正确
-        SmsTemplateDO smsTemplate = smsTemplateMapper.selectById(reqVO.getId()); // 获取最新的
-        assertPojoEquals(reqVO, smsTemplate);
-        assertEquals(Lists.newArrayList("operation", "code"), smsTemplate.getParams());
-        assertEquals(channelDO.getCode(), smsTemplate.getChannelCode());
-    }
-
-    @Test
-    public void testUpdateSmsTemplate_notExists() {
-        // 准备参数
-        SmsTemplateSaveReqVO reqVO = randomPojo(SmsTemplateSaveReqVO.class);
-
-        // 调用, 并断言异常
-        assertServiceException(() -> smsTemplateService.updateSmsTemplate(reqVO), SMS_TEMPLATE_NOT_EXISTS);
-    }
-
-    @Test
-    public void testDeleteSmsTemplate_success() {
-        // mock 数据
-        SmsTemplateDO dbSmsTemplate = randomSmsTemplateDO();
-        smsTemplateMapper.insert(dbSmsTemplate);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        Long id = dbSmsTemplate.getId();
-
-        // 调用
-        smsTemplateService.deleteSmsTemplate(id);
-        // 校验数据不存在了
-        assertNull(smsTemplateMapper.selectById(id));
-    }
-
-    @Test
-    public void testDeleteSmsTemplate_notExists() {
-        // 准备参数
-        Long id = randomLongId();
-
-        // 调用, 并断言异常
-        assertServiceException(() -> smsTemplateService.deleteSmsTemplate(id), SMS_TEMPLATE_NOT_EXISTS);
-    }
-
-    @Test
-    public void testGetSmsTemplate() {
-        // mock 数据
-        SmsTemplateDO dbSmsTemplate = randomSmsTemplateDO();
-        smsTemplateMapper.insert(dbSmsTemplate);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        Long id = dbSmsTemplate.getId();
-
-        // 调用
-        SmsTemplateDO smsTemplate = smsTemplateService.getSmsTemplate(id);
-        // 校验
-        assertPojoEquals(dbSmsTemplate, smsTemplate);
-    }
-
-    @Test
-    public void testGetSmsTemplateByCodeFromCache() {
-        // mock 数据
-        SmsTemplateDO dbSmsTemplate = randomSmsTemplateDO();
-        smsTemplateMapper.insert(dbSmsTemplate);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        String code = dbSmsTemplate.getCode();
-
-        // 调用
-        SmsTemplateDO smsTemplate = smsTemplateService.getSmsTemplateByCodeFromCache(code);
-        // 校验
-        assertPojoEquals(dbSmsTemplate, smsTemplate);
-    }
-
-    @Test
-    public void testGetSmsTemplatePage() {
-        // mock 数据
-        SmsTemplateDO dbSmsTemplate = randomPojo(SmsTemplateDO.class, o -> { // 等会查询到
-            o.setType(SmsTemplateTypeEnum.PROMOTION.getType());
-            o.setStatus(CommonStatusEnum.ENABLE.getStatus());
-            o.setCode("tudou");
-            o.setContent("iailab");
-            o.setApiTemplateId("yunai");
-            o.setChannelId(1L);
-            o.setCreateTime(buildTime(2021, 11, 11));
-        });
-        smsTemplateMapper.insert(dbSmsTemplate);
-        // 测试 type 不匹配
-        smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setType(SmsTemplateTypeEnum.VERIFICATION_CODE.getType())));
-        // 测试 status 不匹配
-        smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
-        // 测试 code 不匹配
-        smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setCode("yuanma")));
-        // 测试 content 不匹配
-        smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setContent("源码")));
-        // 测试 apiTemplateId 不匹配
-        smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setApiTemplateId("nai")));
-        // 测试 channelId 不匹配
-        smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setChannelId(2L)));
-        // 测试 createTime 不匹配
-        smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setCreateTime(buildTime(2021, 12, 12))));
-        // 准备参数
-        SmsTemplatePageReqVO reqVO = new SmsTemplatePageReqVO();
-        reqVO.setType(SmsTemplateTypeEnum.PROMOTION.getType());
-        reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
-        reqVO.setCode("tu");
-        reqVO.setContent("平台");
-        reqVO.setApiTemplateId("yu");
-        reqVO.setChannelId(1L);
-        reqVO.setCreateTime(buildBetweenTime(2021, 11, 1, 2021, 12, 1));
-
-        // 调用
-        PageResult<SmsTemplateDO> pageResult = smsTemplateService.getSmsTemplatePage(reqVO);
-        // 断言
-        assertEquals(1, pageResult.getTotal());
-        assertEquals(1, pageResult.getList().size());
-        assertPojoEquals(dbSmsTemplate, pageResult.getList().get(0));
-    }
-
-    @Test
-    public void testGetSmsTemplateCountByChannelId() {
-        // mock 数据
-        SmsTemplateDO dbSmsTemplate = randomPojo(SmsTemplateDO.class, o -> o.setChannelId(1L));
-        smsTemplateMapper.insert(dbSmsTemplate);
-        // 测试 channelId 不匹配
-        smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setChannelId(2L)));
-        // 准备参数
-        Long channelId = 1L;
-
-        // 调用
-        Long count = smsTemplateService.getSmsTemplateCountByChannelId(channelId);
-        // 断言
-        assertEquals(1, count);
-    }
-
-    @Test
-    public void testValidateSmsChannel_success() {
-        // 准备参数
-        Long channelId = randomLongId();
-        // mock 方法
-        SmsChannelDO channelDO = randomPojo(SmsChannelDO.class, o -> {
-            o.setId(channelId);
-            o.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 保证 status 开启,创建必须处于这个状态
-        });
-        when(smsChannelService.getSmsChannel(eq(channelId))).thenReturn(channelDO);
-
-        // 调用
-        SmsChannelDO returnChannelDO = smsTemplateService.validateSmsChannel(channelId);
-        // 断言
-        assertPojoEquals(returnChannelDO, channelDO);
-    }
-
-    @Test
-    public void testValidateSmsChannel_notExists() {
-        // 准备参数
-        Long channelId = randomLongId();
-
-        // 调用,校验异常
-        assertServiceException(() -> smsTemplateService.validateSmsChannel(channelId),
-                SMS_CHANNEL_NOT_EXISTS);
-    }
-
-    @Test
-    public void testValidateSmsChannel_disable() {
-        // 准备参数
-        Long channelId = randomLongId();
-        // mock 方法
-        SmsChannelDO channelDO = randomPojo(SmsChannelDO.class, o -> {
-            o.setId(channelId);
-            o.setStatus(CommonStatusEnum.DISABLE.getStatus()); // 保证 status 禁用,触发失败
-        });
-        when(smsChannelService.getSmsChannel(eq(channelId))).thenReturn(channelDO);
-
-        // 调用,校验异常
-        assertServiceException(() -> smsTemplateService.validateSmsChannel(channelId),
-                SMS_CHANNEL_DISABLE);
-    }
-
-    @Test
-    public void testValidateDictDataValueUnique_success() {
-        // 调用,成功
-        smsTemplateService.validateSmsTemplateCodeDuplicate(randomLongId(), randomString());
-    }
-
-    @Test
-    public void testValidateSmsTemplateCodeDuplicate_valueDuplicateForCreate() {
-        // 准备参数
-        String code = randomString();
-        // mock 数据
-        smsTemplateMapper.insert(randomSmsTemplateDO(o -> o.setCode(code)));
-
-        // 调用,校验异常
-        assertServiceException(() -> smsTemplateService.validateSmsTemplateCodeDuplicate(null, code),
-                SMS_TEMPLATE_CODE_DUPLICATE, code);
-    }
-
-    @Test
-    public void testValidateDictDataValueUnique_valueDuplicateForUpdate() {
-        // 准备参数
-        Long id = randomLongId();
-        String code = randomString();
-        // mock 数据
-        smsTemplateMapper.insert(randomSmsTemplateDO(o -> o.setCode(code)));
-
-        // 调用,校验异常
-        assertServiceException(() -> smsTemplateService.validateSmsTemplateCodeDuplicate(id, code),
-                SMS_TEMPLATE_CODE_DUPLICATE, code);
-    }
-
-    // ========== 随机对象 ==========
-
-    @SafeVarargs
-    private static SmsTemplateDO randomSmsTemplateDO(Consumer<SmsTemplateDO>... consumers) {
-        Consumer<SmsTemplateDO> consumer = (o) -> {
-            o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围
-            o.setType(randomEle(SmsTemplateTypeEnum.values()).getType()); // 保证 type 的 范围
-        };
-        return randomPojo(SmsTemplateDO.class, ArrayUtils.append(consumer, consumers));
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/social/SocialClientServiceImplTest.java b/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/social/SocialClientServiceImplTest.java
deleted file mode 100644
index 7e51637..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/social/SocialClientServiceImplTest.java
+++ /dev/null
@@ -1,472 +0,0 @@
-package com.iailab.module.system.service.social;
-
-import cn.binarywang.wx.miniapp.api.WxMaService;
-import cn.binarywang.wx.miniapp.api.WxMaUserService;
-import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
-import cn.hutool.core.util.ReflectUtil;
-import com.iailab.framework.common.enums.CommonStatusEnum;
-import com.iailab.framework.common.enums.UserTypeEnum;
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.framework.test.core.ut.BaseDbUnitTest;
-import com.iailab.module.system.controller.admin.socail.vo.client.SocialClientPageReqVO;
-import com.iailab.module.system.controller.admin.socail.vo.client.SocialClientSaveReqVO;
-import com.iailab.module.system.dal.dataobject.social.SocialClientDO;
-import com.iailab.module.system.dal.mysql.social.SocialClientMapper;
-import com.iailab.module.system.enums.social.SocialTypeEnum;
-import com.binarywang.spring.starter.wxjava.miniapp.properties.WxMaProperties;
-import com.binarywang.spring.starter.wxjava.mp.properties.WxMpProperties;
-import com.xingyuv.jushauth.config.AuthConfig;
-import com.xingyuv.jushauth.model.AuthResponse;
-import com.xingyuv.jushauth.model.AuthUser;
-import com.xingyuv.jushauth.request.AuthDefaultRequest;
-import com.xingyuv.jushauth.request.AuthRequest;
-import com.xingyuv.jushauth.utils.AuthStateUtils;
-import com.xingyuv.justauth.AuthRequestFactory;
-import me.chanjar.weixin.common.bean.WxJsapiSignature;
-import me.chanjar.weixin.common.error.WxErrorException;
-import me.chanjar.weixin.mp.api.WxMpService;
-import org.junit.jupiter.api.Test;
-import org.mockito.MockedStatic;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.context.annotation.Import;
-import org.springframework.data.redis.core.StringRedisTemplate;
-
-import javax.annotation.Resource;
-
-import static cn.hutool.core.util.RandomUtil.randomEle;
-import static com.iailab.framework.common.util.object.ObjectUtils.cloneIgnoreId;
-import static com.iailab.framework.test.core.util.AssertUtils.assertPojoEquals;
-import static com.iailab.framework.test.core.util.AssertUtils.assertServiceException;
-import static com.iailab.framework.test.core.util.RandomUtils.*;
-import static com.iailab.module.system.enums.ErrorCodeConstants.*;
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.Mockito.*;
-
-/**
- * {@link SocialClientServiceImpl} 的单元测试类
- *
- * @author iailab
- */
-@Import(SocialClientServiceImpl.class)
-public class SocialClientServiceImplTest extends BaseDbUnitTest {
-
-    @Resource
-    private SocialClientServiceImpl socialClientService;
-
-    @Resource
-    private SocialClientMapper socialClientMapper;
-
-    @MockBean
-    private AuthRequestFactory authRequestFactory;
-
-    @MockBean
-    private WxMpService wxMpService;
-    @MockBean
-    private WxMpProperties wxMpProperties;
-    @MockBean
-    private StringRedisTemplate stringRedisTemplate;
-    @MockBean
-    private WxMaService wxMaService;
-    @MockBean
-    private WxMaProperties wxMaProperties;
-
-    @Test
-    public void testGetAuthorizeUrl() {
-        try (MockedStatic<AuthStateUtils> authStateUtilsMock = mockStatic(AuthStateUtils.class)) {
-            // 准备参数
-            Integer socialType = SocialTypeEnum.WECHAT_MP.getType();
-            Integer userType = randomPojo(UserTypeEnum.class).getValue();
-            String redirectUri = "sss";
-            // mock 获得对应的 AuthRequest 实现
-            AuthRequest authRequest = mock(AuthRequest.class);
-            when(authRequestFactory.get(eq("WECHAT_MP"))).thenReturn(authRequest);
-            // mock 方法
-            authStateUtilsMock.when(AuthStateUtils::createState).thenReturn("aoteman");
-            when(authRequest.authorize(eq("aoteman"))).thenReturn("https://www.baidu.com?redirect_uri=yyy");
-
-            // 调用
-            String url = socialClientService.getAuthorizeUrl(socialType, userType, redirectUri);
-            // 断言
-            assertEquals("https://www.baidu.com?redirect_uri=sss", url);
-        }
-    }
-
-    @Test
-    public void testAuthSocialUser_success() {
-        // 准备参数
-        Integer socialType = SocialTypeEnum.WECHAT_MP.getType();
-        Integer userType = randomPojo(UserTypeEnum.class).getValue();
-        String code = randomString();
-        String state = randomString();
-        // mock 方法(AuthRequest)
-        AuthRequest authRequest = mock(AuthRequest.class);
-        when(authRequestFactory.get(eq("WECHAT_MP"))).thenReturn(authRequest);
-        // mock 方法(AuthResponse)
-        AuthUser authUser = randomPojo(AuthUser.class);
-        AuthResponse<?> authResponse = new AuthResponse<>(2000, null, authUser);
-        when(authRequest.login(argThat(authCallback -> {
-            assertEquals(code, authCallback.getCode());
-            assertEquals(state, authCallback.getState());
-            return true;
-        }))).thenReturn(authResponse);
-
-        // 调用
-        AuthUser result = socialClientService.getAuthUser(socialType, userType, code, state);
-        // 断言
-        assertSame(authUser, result);
-    }
-
-    @Test
-    public void testAuthSocialUser_fail() {
-        // 准备参数
-        Integer socialType = SocialTypeEnum.WECHAT_MP.getType();
-        Integer userType = randomPojo(UserTypeEnum.class).getValue();
-        String code = randomString();
-        String state = randomString();
-        // mock 方法(AuthRequest)
-        AuthRequest authRequest = mock(AuthRequest.class);
-        when(authRequestFactory.get(eq("WECHAT_MP"))).thenReturn(authRequest);
-        // mock 方法(AuthResponse)
-        AuthResponse<?> authResponse = new AuthResponse<>(0, "模拟失败", null);
-        when(authRequest.login(argThat(authCallback -> {
-            assertEquals(code, authCallback.getCode());
-            assertEquals(state, authCallback.getState());
-            return true;
-        }))).thenReturn(authResponse);
-
-        // 调用并断言
-        assertServiceException(
-                () -> socialClientService.getAuthUser(socialType, userType, code, state),
-                SOCIAL_USER_AUTH_FAILURE, "模拟失败");
-    }
-
-    @Test
-    public void testBuildAuthRequest_clientNull() {
-        // 准备参数
-        Integer socialType = SocialTypeEnum.WECHAT_MP.getType();
-        Integer userType = randomPojo(SocialTypeEnum.class).getType();
-        // mock 获得对应的 AuthRequest 实现
-        AuthRequest authRequest = mock(AuthDefaultRequest.class);
-        AuthConfig authConfig = (AuthConfig) ReflectUtil.getFieldValue(authRequest, "config");
-        when(authRequestFactory.get(eq("WECHAT_MP"))).thenReturn(authRequest);
-
-        // 调用
-        AuthRequest result = socialClientService.buildAuthRequest(socialType, userType);
-        // 断言
-        assertSame(authRequest, result);
-        assertSame(authConfig, ReflectUtil.getFieldValue(authConfig, "config"));
-    }
-
-    @Test
-    public void testBuildAuthRequest_clientDisable() {
-        // 准备参数
-        Integer socialType = SocialTypeEnum.WECHAT_MP.getType();
-        Integer userType = randomPojo(SocialTypeEnum.class).getType();
-        // mock 获得对应的 AuthRequest 实现
-        AuthRequest authRequest = mock(AuthDefaultRequest.class);
-        AuthConfig authConfig = (AuthConfig) ReflectUtil.getFieldValue(authRequest, "config");
-        when(authRequestFactory.get(eq("WECHAT_MP"))).thenReturn(authRequest);
-        // mock 数据
-        SocialClientDO client = randomPojo(SocialClientDO.class, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())
-                .setUserType(userType).setSocialType(socialType));
-        socialClientMapper.insert(client);
-
-        // 调用
-        AuthRequest result = socialClientService.buildAuthRequest(socialType, userType);
-        // 断言
-        assertSame(authRequest, result);
-        assertSame(authConfig, ReflectUtil.getFieldValue(authConfig, "config"));
-    }
-
-    @Test
-    public void testBuildAuthRequest_clientEnable() {
-        // 准备参数
-        Integer socialType = SocialTypeEnum.WECHAT_MP.getType();
-        Integer userType = randomPojo(SocialTypeEnum.class).getType();
-        // mock 获得对应的 AuthRequest 实现
-        AuthConfig authConfig = mock(AuthConfig.class);
-        AuthRequest authRequest = mock(AuthDefaultRequest.class);
-        ReflectUtil.setFieldValue(authRequest, "config", authConfig);
-        when(authRequestFactory.get(eq("WECHAT_MP"))).thenReturn(authRequest);
-        // mock 数据
-        SocialClientDO client = randomPojo(SocialClientDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())
-                .setUserType(userType).setSocialType(socialType));
-        socialClientMapper.insert(client);
-
-        // 调用
-        AuthRequest result = socialClientService.buildAuthRequest(socialType, userType);
-        // 断言
-        assertSame(authRequest, result);
-        assertNotSame(authConfig, ReflectUtil.getFieldValue(authRequest, "config"));
-    }
-
-    // =================== 微信公众号独有 ===================
-
-    @Test
-    public void testCreateWxMpJsapiSignature() throws WxErrorException {
-        // 准备参数
-        Integer userType = randomPojo(UserTypeEnum.class).getValue();
-        String url = randomString();
-        // mock 方法
-        WxJsapiSignature signature = randomPojo(WxJsapiSignature.class);
-        when(wxMpService.createJsapiSignature(eq(url))).thenReturn(signature);
-
-        // 调用
-        WxJsapiSignature result = socialClientService.createWxMpJsapiSignature(userType, url);
-        // 断言
-        assertSame(signature, result);
-    }
-
-    @Test
-    public void testGetWxMpService_clientNull() {
-        // 准备参数
-        Integer userType = randomPojo(UserTypeEnum.class).getValue();
-        // mock 方法
-
-        // 调用
-        WxMpService result = socialClientService.getWxMpService(userType);
-        // 断言
-        assertSame(wxMpService, result);
-    }
-
-    @Test
-    public void testGetWxMpService_clientDisable() {
-        // 准备参数
-        Integer userType = randomPojo(UserTypeEnum.class).getValue();
-        // mock 数据
-        SocialClientDO client = randomPojo(SocialClientDO.class, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())
-                .setUserType(userType).setSocialType(SocialTypeEnum.WECHAT_MP.getType()));
-        socialClientMapper.insert(client);
-
-        // 调用
-        WxMpService result = socialClientService.getWxMpService(userType);
-        // 断言
-        assertSame(wxMpService, result);
-    }
-
-    @Test
-    public void testGetWxMpService_clientEnable() {
-        // 准备参数
-        Integer userType = randomPojo(UserTypeEnum.class).getValue();
-        // mock 数据
-        SocialClientDO client = randomPojo(SocialClientDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())
-                .setUserType(userType).setSocialType(SocialTypeEnum.WECHAT_MP.getType()));
-        socialClientMapper.insert(client);
-        // mock 方法
-        WxMpProperties.ConfigStorage configStorage = mock(WxMpProperties.ConfigStorage.class);
-        when(wxMpProperties.getConfigStorage()).thenReturn(configStorage);
-
-        // 调用
-        WxMpService result = socialClientService.getWxMpService(userType);
-        // 断言
-        assertNotSame(wxMpService, result);
-        assertEquals(client.getClientId(), result.getWxMpConfigStorage().getAppId());
-        assertEquals(client.getClientSecret(), result.getWxMpConfigStorage().getSecret());
-    }
-
-    // =================== 微信小程序独有 ===================
-
-    @Test
-    public void testGetWxMaPhoneNumberInfo_success() throws WxErrorException {
-        // 准备参数
-        Integer userType = randomPojo(UserTypeEnum.class).getValue();
-        String phoneCode = randomString();
-        // mock 方法
-        WxMaUserService userService = mock(WxMaUserService.class);
-        when(wxMaService.getUserService()).thenReturn(userService);
-        WxMaPhoneNumberInfo phoneNumber = randomPojo(WxMaPhoneNumberInfo.class);
-        when(userService.getPhoneNoInfo(eq(phoneCode))).thenReturn(phoneNumber);
-
-        // 调用
-        WxMaPhoneNumberInfo result = socialClientService.getWxMaPhoneNumberInfo(userType, phoneCode);
-        // 断言
-        assertSame(phoneNumber, result);
-    }
-
-    @Test
-    public void testGetWxMaPhoneNumberInfo_exception() throws WxErrorException {
-        // 准备参数
-        Integer userType = randomPojo(UserTypeEnum.class).getValue();
-        String phoneCode = randomString();
-        // mock 方法
-        WxMaUserService userService = mock(WxMaUserService.class);
-        when(wxMaService.getUserService()).thenReturn(userService);
-        WxErrorException wxErrorException = randomPojo(WxErrorException.class);
-        when(userService.getPhoneNoInfo(eq(phoneCode))).thenThrow(wxErrorException);
-
-        // 调用并断言异常
-        assertServiceException(() -> socialClientService.getWxMaPhoneNumberInfo(userType, phoneCode),
-                SOCIAL_CLIENT_WEIXIN_MINI_APP_PHONE_CODE_ERROR);
-    }
-
-    @Test
-    public void testGetWxMaService_clientNull() {
-        // 准备参数
-        Integer userType = randomPojo(UserTypeEnum.class).getValue();
-        // mock 方法
-
-        // 调用
-        WxMaService result = socialClientService.getWxMaService(userType);
-        // 断言
-        assertSame(wxMaService, result);
-    }
-
-    @Test
-    public void testGetWxMaService_clientDisable() {
-        // 准备参数
-        Integer userType = randomPojo(UserTypeEnum.class).getValue();
-        // mock 数据
-        SocialClientDO client = randomPojo(SocialClientDO.class, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())
-                .setUserType(userType).setSocialType(SocialTypeEnum.WECHAT_MINI_APP.getType()));
-        socialClientMapper.insert(client);
-
-        // 调用
-        WxMaService result = socialClientService.getWxMaService(userType);
-        // 断言
-        assertSame(wxMaService, result);
-    }
-
-    @Test
-    public void testGetWxMaService_clientEnable() {
-        // 准备参数
-        Integer userType = randomPojo(UserTypeEnum.class).getValue();
-        // mock 数据
-        SocialClientDO client = randomPojo(SocialClientDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())
-                .setUserType(userType).setSocialType(SocialTypeEnum.WECHAT_MINI_APP.getType()));
-        socialClientMapper.insert(client);
-        // mock 方法
-        WxMaProperties.ConfigStorage configStorage = mock(WxMaProperties.ConfigStorage.class);
-        when(wxMaProperties.getConfigStorage()).thenReturn(configStorage);
-
-        // 调用
-        WxMaService result = socialClientService.getWxMaService(userType);
-        // 断言
-        assertNotSame(wxMaService, result);
-        assertEquals(client.getClientId(), result.getWxMaConfig().getAppid());
-        assertEquals(client.getClientSecret(), result.getWxMaConfig().getSecret());
-    }
-
-    // =================== 客户端管理 ===================
-
-    @Test
-    public void testCreateSocialClient_success() {
-        // 准备参数
-        SocialClientSaveReqVO reqVO = randomPojo(SocialClientSaveReqVO.class,
-                o -> o.setSocialType(randomEle(SocialTypeEnum.values()).getType())
-                        .setUserType(randomEle(UserTypeEnum.values()).getValue())
-                        .setStatus(randomCommonStatus()))
-                .setId(null); // 防止 id 被赋值
-
-        // 调用
-        Long socialClientId = socialClientService.createSocialClient(reqVO);
-        // 断言
-        assertNotNull(socialClientId);
-        // 校验记录的属性是否正确
-        SocialClientDO socialClient = socialClientMapper.selectById(socialClientId);
-        assertPojoEquals(reqVO, socialClient, "id");
-    }
-
-    @Test
-    public void testUpdateSocialClient_success() {
-        // mock 数据
-        SocialClientDO dbSocialClient = randomPojo(SocialClientDO.class);
-        socialClientMapper.insert(dbSocialClient);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        SocialClientSaveReqVO reqVO = randomPojo(SocialClientSaveReqVO.class, o -> {
-            o.setId(dbSocialClient.getId()); // 设置更新的 ID
-            o.setSocialType(randomEle(SocialTypeEnum.values()).getType())
-                    .setUserType(randomEle(UserTypeEnum.values()).getValue())
-                    .setStatus(randomCommonStatus());
-        });
-
-        // 调用
-        socialClientService.updateSocialClient(reqVO);
-        // 校验是否更新正确
-        SocialClientDO socialClient = socialClientMapper.selectById(reqVO.getId()); // 获取最新的
-        assertPojoEquals(reqVO, socialClient);
-    }
-
-    @Test
-    public void testUpdateSocialClient_notExists() {
-        // 准备参数
-        SocialClientSaveReqVO reqVO = randomPojo(SocialClientSaveReqVO.class);
-
-        // 调用, 并断言异常
-        assertServiceException(() -> socialClientService.updateSocialClient(reqVO), SOCIAL_CLIENT_NOT_EXISTS);
-    }
-
-    @Test
-    public void testDeleteSocialClient_success() {
-        // mock 数据
-        SocialClientDO dbSocialClient = randomPojo(SocialClientDO.class);
-        socialClientMapper.insert(dbSocialClient);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        Long id = dbSocialClient.getId();
-
-        // 调用
-        socialClientService.deleteSocialClient(id);
-        // 校验数据不存在了
-        assertNull(socialClientMapper.selectById(id));
-    }
-
-    @Test
-    public void testDeleteSocialClient_notExists() {
-        // 准备参数
-        Long id = randomLongId();
-
-        // 调用, 并断言异常
-        assertServiceException(() -> socialClientService.deleteSocialClient(id), SOCIAL_CLIENT_NOT_EXISTS);
-    }
-
-    @Test
-    public void testGetSocialClient() {
-        // mock 数据
-        SocialClientDO dbSocialClient = randomPojo(SocialClientDO.class);
-        socialClientMapper.insert(dbSocialClient);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        Long id = dbSocialClient.getId();
-
-        // 调用
-        SocialClientDO socialClient = socialClientService.getSocialClient(id);
-        // 校验数据正确
-        assertPojoEquals(dbSocialClient, socialClient);
-    }
-
-    @Test
-    public void testGetSocialClientPage() {
-        // mock 数据
-        SocialClientDO dbSocialClient = randomPojo(SocialClientDO.class, o -> { // 等会查询到
-            o.setName("芋头");
-            o.setSocialType(SocialTypeEnum.GITEE.getType());
-            o.setUserType(UserTypeEnum.ADMIN.getValue());
-            o.setClientId("iailab");
-            o.setStatus(CommonStatusEnum.ENABLE.getStatus());
-        });
-        socialClientMapper.insert(dbSocialClient);
-        // 测试 name 不匹配
-        socialClientMapper.insert(cloneIgnoreId(dbSocialClient, o -> o.setName(randomString())));
-        // 测试 socialType 不匹配
-        socialClientMapper.insert(cloneIgnoreId(dbSocialClient, o -> o.setSocialType(SocialTypeEnum.DINGTALK.getType())));
-        // 测试 userType 不匹配
-        socialClientMapper.insert(cloneIgnoreId(dbSocialClient, o -> o.setUserType(UserTypeEnum.MEMBER.getValue())));
-        // 测试 clientId 不匹配
-        socialClientMapper.insert(cloneIgnoreId(dbSocialClient, o -> o.setClientId("dao")));
-        // 测试 status 不匹配
-        socialClientMapper.insert(cloneIgnoreId(dbSocialClient, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
-        // 准备参数
-        SocialClientPageReqVO reqVO = new SocialClientPageReqVO();
-        reqVO.setName("芋");
-        reqVO.setSocialType(SocialTypeEnum.GITEE.getType());
-        reqVO.setUserType(UserTypeEnum.ADMIN.getValue());
-        reqVO.setClientId("yu");
-        reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
-
-        // 调用
-        PageResult<SocialClientDO> pageResult = socialClientService.getSocialClientPage(reqVO);
-        // 断言
-        assertEquals(1, pageResult.getTotal());
-        assertEquals(1, pageResult.getList().size());
-        assertPojoEquals(dbSocialClient, pageResult.getList().get(0));
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/social/SocialUserServiceImplTest.java b/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/social/SocialUserServiceImplTest.java
deleted file mode 100644
index 3e1320a..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/social/SocialUserServiceImplTest.java
+++ /dev/null
@@ -1,288 +0,0 @@
-package com.iailab.module.system.service.social;
-
-import com.iailab.framework.common.enums.UserTypeEnum;
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.framework.test.core.ut.BaseDbUnitTest;
-import com.iailab.module.system.api.social.dto.SocialUserBindReqDTO;
-import com.iailab.module.system.api.social.dto.SocialUserRespDTO;
-import com.iailab.module.system.controller.admin.socail.vo.user.SocialUserPageReqVO;
-import com.iailab.module.system.dal.dataobject.social.SocialUserBindDO;
-import com.iailab.module.system.dal.dataobject.social.SocialUserDO;
-import com.iailab.module.system.dal.mysql.social.SocialUserBindMapper;
-import com.iailab.module.system.dal.mysql.social.SocialUserMapper;
-import com.iailab.module.system.enums.social.SocialTypeEnum;
-import com.xingyuv.jushauth.model.AuthUser;
-import org.junit.jupiter.api.Test;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.context.annotation.Import;
-
-import javax.annotation.Resource;
-import java.util.List;
-
-import static cn.hutool.core.util.RandomUtil.randomEle;
-import static cn.hutool.core.util.RandomUtil.randomLong;
-import static com.iailab.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
-import static com.iailab.framework.common.util.date.LocalDateTimeUtils.buildTime;
-import static com.iailab.framework.common.util.json.JsonUtils.toJsonString;
-import static com.iailab.framework.common.util.object.ObjectUtils.cloneIgnoreId;
-import static com.iailab.framework.test.core.util.AssertUtils.assertPojoEquals;
-import static com.iailab.framework.test.core.util.AssertUtils.assertServiceException;
-import static com.iailab.framework.test.core.util.RandomUtils.randomPojo;
-import static com.iailab.framework.test.core.util.RandomUtils.randomString;
-import static com.iailab.module.system.enums.ErrorCodeConstants.SOCIAL_USER_NOT_FOUND;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.when;
-
-/**
- * {@link SocialUserServiceImpl} 的单元测试类
- *
- * @author iailab
- */
-@Import(SocialUserServiceImpl.class)
-public class SocialUserServiceImplTest extends BaseDbUnitTest {
-
-    @Resource
-    private SocialUserServiceImpl socialUserService;
-
-    @Resource
-    private SocialUserMapper socialUserMapper;
-    @Resource
-    private SocialUserBindMapper socialUserBindMapper;
-
-    @MockBean
-    private SocialClientService socialClientService;
-
-    @Test
-    public void testGetSocialUserList() {
-        Long userId = 1L;
-        Integer userType = UserTypeEnum.ADMIN.getValue();
-        // mock 获得社交用户
-        SocialUserDO socialUser = randomPojo(SocialUserDO.class).setType(SocialTypeEnum.GITEE.getType());
-        socialUserMapper.insert(socialUser); // 可被查到
-        socialUserMapper.insert(randomPojo(SocialUserDO.class)); // 不可被查到
-        // mock 获得绑定
-        socialUserBindMapper.insert(randomPojo(SocialUserBindDO.class) // 可被查询到
-                .setUserId(userId).setUserType(userType).setSocialType(SocialTypeEnum.GITEE.getType())
-                .setSocialUserId(socialUser.getId()));
-        socialUserBindMapper.insert(randomPojo(SocialUserBindDO.class) // 不可被查询到
-                .setUserId(2L).setUserType(userType).setSocialType(SocialTypeEnum.DINGTALK.getType()));
-
-        // 调用
-        List<SocialUserDO> result = socialUserService.getSocialUserList(userId, userType);
-        // 断言
-        assertEquals(1, result.size());
-        assertPojoEquals(socialUser, result.get(0));
-    }
-
-    @Test
-    public void testBindSocialUser() {
-        // 准备参数
-        SocialUserBindReqDTO reqDTO = new SocialUserBindReqDTO()
-                .setUserId(1L).setUserType(UserTypeEnum.ADMIN.getValue())
-                .setSocialType(SocialTypeEnum.GITEE.getType()).setCode("test_code").setState("test_state");
-        // mock 数据:获得社交用户
-        SocialUserDO socialUser = randomPojo(SocialUserDO.class).setType(reqDTO.getSocialType())
-                .setCode(reqDTO.getCode()).setState(reqDTO.getState());
-        socialUserMapper.insert(socialUser);
-        // mock 数据:用户可能之前已经绑定过该社交类型
-        socialUserBindMapper.insert(randomPojo(SocialUserBindDO.class).setUserId(1L).setUserType(UserTypeEnum.ADMIN.getValue())
-                .setSocialType(SocialTypeEnum.GITEE.getType()).setSocialUserId(-1L));
-        // mock 数据:社交用户可能之前绑定过别的用户
-        socialUserBindMapper.insert(randomPojo(SocialUserBindDO.class).setUserType(UserTypeEnum.ADMIN.getValue())
-                .setSocialType(SocialTypeEnum.GITEE.getType()).setSocialUserId(socialUser.getId()));
-
-        // 调用
-        String openid = socialUserService.bindSocialUser(reqDTO);
-        // 断言
-        List<SocialUserBindDO> socialUserBinds = socialUserBindMapper.selectList();
-        assertEquals(1, socialUserBinds.size());
-        assertEquals(socialUser.getOpenid(), openid);
-    }
-
-    @Test
-    public void testUnbindSocialUser_success() {
-        // 准备参数
-        Long userId = 1L;
-        Integer userType = UserTypeEnum.ADMIN.getValue();
-        Integer type = SocialTypeEnum.GITEE.getType();
-        String openid = "test_openid";
-        // mock 数据:社交用户
-        SocialUserDO socialUser = randomPojo(SocialUserDO.class).setType(type).setOpenid(openid);
-        socialUserMapper.insert(socialUser);
-        // mock 数据:社交绑定关系
-        SocialUserBindDO socialUserBind = randomPojo(SocialUserBindDO.class).setUserType(userType)
-                .setUserId(userId).setSocialType(type);
-        socialUserBindMapper.insert(socialUserBind);
-
-        // 调用
-        socialUserService.unbindSocialUser(userId, userType, type, openid);
-        // 断言
-        assertEquals(0, socialUserBindMapper.selectCount(null).intValue());
-    }
-
-    @Test
-    public void testUnbindSocialUser_notFound() {
-        // 调用,并断言
-        assertServiceException(
-                () -> socialUserService.unbindSocialUser(randomLong(), UserTypeEnum.ADMIN.getValue(),
-                        SocialTypeEnum.GITEE.getType(), "test_openid"),
-                SOCIAL_USER_NOT_FOUND);
-    }
-
-    @Test
-    public void testGetSocialUser() {
-        // 准备参数
-        Integer userType = UserTypeEnum.ADMIN.getValue();
-        Integer type = SocialTypeEnum.GITEE.getType();
-        String code = "tudou";
-        String state = "yuanma";
-        // mock 社交用户
-        SocialUserDO socialUserDO = randomPojo(SocialUserDO.class).setType(type).setCode(code).setState(state);
-        socialUserMapper.insert(socialUserDO);
-        // mock 社交用户的绑定
-        Long userId = randomLong();
-        SocialUserBindDO socialUserBind = randomPojo(SocialUserBindDO.class).setUserType(userType).setUserId(userId)
-                .setSocialType(type).setSocialUserId(socialUserDO.getId());
-        socialUserBindMapper.insert(socialUserBind);
-
-        // 调用
-        SocialUserRespDTO socialUser = socialUserService.getSocialUserByCode(userType, type, code, state);
-        // 断言
-        assertEquals(userId, socialUser.getUserId());
-        assertEquals(socialUserDO.getOpenid(), socialUser.getOpenid());
-    }
-
-    @Test
-    public void testAuthSocialUser_exists() {
-        // 准备参数
-        Integer socialType = SocialTypeEnum.GITEE.getType();
-        Integer userType = randomEle(SocialTypeEnum.values()).getType();
-        String code = "tudou";
-        String state = "yuanma";
-        // mock 方法
-        SocialUserDO socialUser = randomPojo(SocialUserDO.class).setType(socialType).setCode(code).setState(state);
-        socialUserMapper.insert(socialUser);
-
-        // 调用
-        SocialUserDO result = socialUserService.authSocialUser(socialType, userType, code, state);
-        // 断言
-        assertPojoEquals(socialUser, result);
-    }
-
-    @Test
-    public void testAuthSocialUser_notNull() {
-        // mock 数据
-        SocialUserDO socialUser = randomPojo(SocialUserDO.class,
-                o -> o.setType(SocialTypeEnum.GITEE.getType()).setCode("tudou").setState("yuanma"));
-        socialUserMapper.insert(socialUser);
-        // 准备参数
-        Integer socialType = SocialTypeEnum.GITEE.getType();
-        Integer userType = randomEle(SocialTypeEnum.values()).getType();
-        String code = "tudou";
-        String state = "yuanma";
-
-        // 调用
-        SocialUserDO result = socialUserService.authSocialUser(socialType, userType, code, state);
-        // 断言
-        assertPojoEquals(socialUser, result);
-    }
-
-    @Test
-    public void testAuthSocialUser_insert() {
-        // 准备参数
-        Integer socialType = SocialTypeEnum.GITEE.getType();
-        Integer userType = randomEle(SocialTypeEnum.values()).getType();
-        String code = "tudou";
-        String state = "yuanma";
-        // mock 方法
-        AuthUser authUser = randomPojo(AuthUser.class);
-        when(socialClientService.getAuthUser(eq(socialType), eq(userType), eq(code), eq(state))).thenReturn(authUser);
-
-        // 调用
-        SocialUserDO result = socialUserService.authSocialUser(socialType, userType, code, state);
-        // 断言
-        assertBindSocialUser(socialType, result, authUser);
-        assertEquals(code, result.getCode());
-        assertEquals(state, result.getState());
-    }
-
-    @Test
-    public void testAuthSocialUser_update() {
-        // 准备参数
-        Integer socialType = SocialTypeEnum.GITEE.getType();
-        Integer userType = randomEle(SocialTypeEnum.values()).getType();
-        String code = "tudou";
-        String state = "yuanma";
-        // mock 数据
-        socialUserMapper.insert(randomPojo(SocialUserDO.class).setType(socialType).setOpenid("test_openid"));
-        // mock 方法
-        AuthUser authUser = randomPojo(AuthUser.class);
-        when(socialClientService.getAuthUser(eq(socialType), eq(userType), eq(code), eq(state))).thenReturn(authUser);
-
-        // 调用
-        SocialUserDO result = socialUserService.authSocialUser(socialType, userType, code, state);
-        // 断言
-        assertBindSocialUser(socialType, result, authUser);
-        assertEquals(code, result.getCode());
-        assertEquals(state, result.getState());
-    }
-
-    private void assertBindSocialUser(Integer type, SocialUserDO socialUser, AuthUser authUser) {
-        assertEquals(authUser.getToken().getAccessToken(), socialUser.getToken());
-        assertEquals(toJsonString(authUser.getToken()), socialUser.getRawTokenInfo());
-        assertEquals(authUser.getNickname(), socialUser.getNickname());
-        assertEquals(authUser.getAvatar(), socialUser.getAvatar());
-        assertEquals(toJsonString(authUser.getRawUserInfo()), socialUser.getRawUserInfo());
-        assertEquals(type, socialUser.getType());
-        assertEquals(authUser.getUuid(), socialUser.getOpenid());
-    }
-
-    @Test
-    public void testGetSocialUser_id() {
-        // mock 数据
-        SocialUserDO socialUserDO = randomPojo(SocialUserDO.class);
-        socialUserMapper.insert(socialUserDO);
-        // 参数准备
-        Long id = socialUserDO.getId();
-
-        // 调用
-        SocialUserDO dbSocialUserDO = socialUserService.getSocialUser(id);
-        // 断言
-        assertPojoEquals(socialUserDO, dbSocialUserDO);
-    }
-
-    @Test
-    public void testGetSocialUserPage() {
-        // mock 数据
-        SocialUserDO dbSocialUser = randomPojo(SocialUserDO.class, o -> { // 等会查询到
-            o.setType(SocialTypeEnum.GITEE.getType());
-            o.setNickname("iailab");
-            o.setOpenid("iailabyuanma");
-            o.setCreateTime(buildTime(2020, 1, 15));
-        });
-        socialUserMapper.insert(dbSocialUser);
-        // 测试 type 不匹配
-        socialUserMapper.insert(cloneIgnoreId(dbSocialUser, o -> o.setType(SocialTypeEnum.DINGTALK.getType())));
-        // 测试 nickname 不匹配
-        socialUserMapper.insert(cloneIgnoreId(dbSocialUser, o -> o.setNickname(randomString())));
-        // 测试 openid 不匹配
-        socialUserMapper.insert(cloneIgnoreId(dbSocialUser, o -> o.setOpenid("java")));
-        // 测试 createTime 不匹配
-        socialUserMapper.insert(cloneIgnoreId(dbSocialUser, o -> o.setCreateTime(buildTime(2020, 1, 21))));
-        // 准备参数
-        SocialUserPageReqVO reqVO = new SocialUserPageReqVO();
-        reqVO.setType(SocialTypeEnum.GITEE.getType());
-        reqVO.setNickname("芋");
-        reqVO.setOpenid("iailab");
-        reqVO.setCreateTime(buildBetweenTime(2020, 1, 10, 2020, 1, 20));
-
-        // 调用
-        PageResult<SocialUserDO> pageResult = socialUserService.getSocialUserPage(reqVO);
-        // 断言
-        assertEquals(1, pageResult.getTotal());
-        assertEquals(1, pageResult.getList().size());
-        assertPojoEquals(dbSocialUser, pageResult.getList().get(0));
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/tenant/TenantPackageServiceImplTest.java b/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/tenant/TenantPackageServiceImplTest.java
deleted file mode 100644
index c35c588..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/tenant/TenantPackageServiceImplTest.java
+++ /dev/null
@@ -1,236 +0,0 @@
-package com.iailab.module.system.service.tenant;
-
-import com.iailab.framework.common.enums.CommonStatusEnum;
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.framework.test.core.ut.BaseDbUnitTest;
-import com.iailab.module.system.controller.admin.tenant.vo.packages.TenantPackagePageReqVO;
-import com.iailab.module.system.controller.admin.tenant.vo.packages.TenantPackageSaveReqVO;
-import com.iailab.module.system.dal.dataobject.tenant.TenantDO;
-import com.iailab.module.system.dal.dataobject.tenant.TenantPackageDO;
-import com.iailab.module.system.dal.mysql.tenant.TenantPackageMapper;
-import org.junit.jupiter.api.Test;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.context.annotation.Import;
-
-import javax.annotation.Resource;
-import java.util.List;
-
-import static com.iailab.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
-import static com.iailab.framework.common.util.date.LocalDateTimeUtils.buildTime;
-import static com.iailab.framework.common.util.object.ObjectUtils.cloneIgnoreId;
-import static com.iailab.framework.test.core.util.AssertUtils.assertPojoEquals;
-import static com.iailab.framework.test.core.util.AssertUtils.assertServiceException;
-import static com.iailab.framework.test.core.util.RandomUtils.*;
-import static com.iailab.module.system.enums.ErrorCodeConstants.*;
-import static java.util.Arrays.asList;
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-/**
-* {@link TenantPackageServiceImpl} 的单元测试类
-*
-* @author iailab
-*/
-@Import(TenantPackageServiceImpl.class)
-public class TenantPackageServiceImplTest extends BaseDbUnitTest {
-
-    @Resource
-    private TenantPackageServiceImpl tenantPackageService;
-
-    @Resource
-    private TenantPackageMapper tenantPackageMapper;
-
-    @MockBean
-    private TenantService tenantService;
-
-    @Test
-    public void testCreateTenantPackage_success() {
-        // 准备参数
-        TenantPackageSaveReqVO reqVO = randomPojo(TenantPackageSaveReqVO.class,
-                o -> o.setStatus(randomCommonStatus()))
-                .setId(null); // 防止 id 被赋值
-
-        // 调用
-        Long tenantPackageId = tenantPackageService.createTenantPackage(reqVO);
-        // 断言
-        assertNotNull(tenantPackageId);
-        // 校验记录的属性是否正确
-        TenantPackageDO tenantPackage = tenantPackageMapper.selectById(tenantPackageId);
-        assertPojoEquals(reqVO, tenantPackage, "id");
-    }
-
-    @Test
-    public void testUpdateTenantPackage_success() {
-        // mock 数据
-        TenantPackageDO dbTenantPackage = randomPojo(TenantPackageDO.class,
-                o -> o.setStatus(randomCommonStatus()));
-        tenantPackageMapper.insert(dbTenantPackage);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        TenantPackageSaveReqVO reqVO = randomPojo(TenantPackageSaveReqVO.class, o -> {
-            o.setId(dbTenantPackage.getId()); // 设置更新的 ID
-            o.setStatus(randomCommonStatus());
-        });
-        // mock 方法
-        Long tenantId01 = randomLongId();
-        Long tenantId02 = randomLongId();
-        when(tenantService.getTenantListByPackageId(eq(reqVO.getId()))).thenReturn(
-                asList(randomPojo(TenantDO.class, o -> o.setId(tenantId01)),
-                        randomPojo(TenantDO.class, o -> o.setId(tenantId02))));
-
-        // 调用
-        tenantPackageService.updateTenantPackage(reqVO);
-        // 校验是否更新正确
-        TenantPackageDO tenantPackage = tenantPackageMapper.selectById(reqVO.getId()); // 获取最新的
-        assertPojoEquals(reqVO, tenantPackage);
-        // 校验调用租户的菜单
-        verify(tenantService).updateTenantRoleMenu(eq(tenantId01), eq(reqVO.getMenuIds()));
-        verify(tenantService).updateTenantRoleMenu(eq(tenantId02), eq(reqVO.getMenuIds()));
-    }
-
-    @Test
-    public void testUpdateTenantPackage_notExists() {
-        // 准备参数
-        TenantPackageSaveReqVO reqVO = randomPojo(TenantPackageSaveReqVO.class);
-
-        // 调用, 并断言异常
-        assertServiceException(() -> tenantPackageService.updateTenantPackage(reqVO), TENANT_PACKAGE_NOT_EXISTS);
-    }
-
-    @Test
-    public void testDeleteTenantPackage_success() {
-        // mock 数据
-        TenantPackageDO dbTenantPackage = randomPojo(TenantPackageDO.class);
-        tenantPackageMapper.insert(dbTenantPackage);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        Long id = dbTenantPackage.getId();
-        // mock 租户未使用该套餐
-        when(tenantService.getTenantCountByPackageId(eq(id))).thenReturn(0L);
-
-        // 调用
-        tenantPackageService.deleteTenantPackage(id);
-       // 校验数据不存在了
-       assertNull(tenantPackageMapper.selectById(id));
-    }
-
-    @Test
-    public void testDeleteTenantPackage_notExists() {
-        // 准备参数
-        Long id = randomLongId();
-
-        // 调用, 并断言异常
-        assertServiceException(() -> tenantPackageService.deleteTenantPackage(id), TENANT_PACKAGE_NOT_EXISTS);
-    }
-
-    @Test
-    public void testDeleteTenantPackage_used() {
-        // mock 数据
-        TenantPackageDO dbTenantPackage = randomPojo(TenantPackageDO.class);
-        tenantPackageMapper.insert(dbTenantPackage);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        Long id = dbTenantPackage.getId();
-        // mock 租户在使用该套餐
-        when(tenantService.getTenantCountByPackageId(eq(id))).thenReturn(1L);
-
-        // 调用, 并断言异常
-        assertServiceException(() -> tenantPackageService.deleteTenantPackage(id), TENANT_PACKAGE_USED);
-    }
-
-    @Test
-    public void testGetTenantPackagePage() {
-       // mock 数据
-       TenantPackageDO dbTenantPackage = randomPojo(TenantPackageDO.class, o -> { // 等会查询到
-           o.setName("iailab");
-           o.setStatus(CommonStatusEnum.ENABLE.getStatus());
-           o.setRemark("源码解析");
-           o.setCreateTime(buildTime(2022, 10, 10));
-       });
-       tenantPackageMapper.insert(dbTenantPackage);
-       // 测试 name 不匹配
-       tenantPackageMapper.insert(cloneIgnoreId(dbTenantPackage, o -> o.setName("源码")));
-       // 测试 status 不匹配
-       tenantPackageMapper.insert(cloneIgnoreId(dbTenantPackage, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
-       // 测试 remark 不匹配
-       tenantPackageMapper.insert(cloneIgnoreId(dbTenantPackage, o -> o.setRemark("解析")));
-       // 测试 createTime 不匹配
-       tenantPackageMapper.insert(cloneIgnoreId(dbTenantPackage, o -> o.setCreateTime(buildTime(2022, 11, 11))));
-       // 准备参数
-       TenantPackagePageReqVO reqVO = new TenantPackagePageReqVO();
-       reqVO.setName("平台");
-       reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
-       reqVO.setRemark("源码");
-       reqVO.setCreateTime(buildBetweenTime(2022, 10, 9, 2022, 10, 11));
-
-       // 调用
-       PageResult<TenantPackageDO> pageResult = tenantPackageService.getTenantPackagePage(reqVO);
-       // 断言
-       assertEquals(1, pageResult.getTotal());
-       assertEquals(1, pageResult.getList().size());
-       assertPojoEquals(dbTenantPackage, pageResult.getList().get(0));
-    }
-
-    @Test
-    public void testValidTenantPackage_success() {
-        // mock 数据
-        TenantPackageDO dbTenantPackage = randomPojo(TenantPackageDO.class,
-                o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus()));
-        tenantPackageMapper.insert(dbTenantPackage);// @Sql: 先插入出一条存在的数据
-
-        // 调用
-        TenantPackageDO result = tenantPackageService.validTenantPackage(dbTenantPackage.getId());
-        // 断言
-        assertPojoEquals(dbTenantPackage, result);
-    }
-
-    @Test
-    public void testValidTenantPackage_notExists() {
-        // 准备参数
-        Long id = randomLongId();
-
-        // 调用, 并断言异常
-        assertServiceException(() -> tenantPackageService.validTenantPackage(id), TENANT_PACKAGE_NOT_EXISTS);
-    }
-
-    @Test
-    public void testValidTenantPackage_disable() {
-        // mock 数据
-        TenantPackageDO dbTenantPackage = randomPojo(TenantPackageDO.class,
-                o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()));
-        tenantPackageMapper.insert(dbTenantPackage);// @Sql: 先插入出一条存在的数据
-
-        // 调用, 并断言异常
-        assertServiceException(() -> tenantPackageService.validTenantPackage(dbTenantPackage.getId()),
-                TENANT_PACKAGE_DISABLE, dbTenantPackage.getName());
-    }
-
-    @Test
-    public void testGetTenantPackage() {
-        // mock 数据
-        TenantPackageDO dbTenantPackage = randomPojo(TenantPackageDO.class);
-        tenantPackageMapper.insert(dbTenantPackage);// @Sql: 先插入出一条存在的数据
-
-        // 调用
-        TenantPackageDO result = tenantPackageService.getTenantPackage(dbTenantPackage.getId());
-        // 断言
-        assertPojoEquals(result, dbTenantPackage);
-    }
-
-    @Test
-    public void testGetTenantPackageListByStatus() {
-        // mock 数据
-        TenantPackageDO dbTenantPackage = randomPojo(TenantPackageDO.class,
-                o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus()));
-        tenantPackageMapper.insert(dbTenantPackage);
-        // 测试 status 不匹配
-        tenantPackageMapper.insert(cloneIgnoreId(dbTenantPackage,
-                o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
-
-        // 调用
-        List<TenantPackageDO> list = tenantPackageService.getTenantPackageListByStatus(
-                CommonStatusEnum.ENABLE.getStatus());
-        assertEquals(1, list.size());
-        assertPojoEquals(dbTenantPackage, list.get(0));
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/tenant/TenantServiceImplTest.java b/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/tenant/TenantServiceImplTest.java
deleted file mode 100644
index ec17796..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/tenant/TenantServiceImplTest.java
+++ /dev/null
@@ -1,458 +0,0 @@
-package com.iailab.module.system.service.tenant;
-
-import com.iailab.framework.common.enums.CommonStatusEnum;
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.framework.tenant.config.TenantProperties;
-import com.iailab.framework.tenant.core.context.TenantContextHolder;
-import com.iailab.framework.test.core.ut.BaseDbUnitTest;
-import com.iailab.module.system.controller.admin.tenant.vo.tenant.TenantPageReqVO;
-import com.iailab.module.system.controller.admin.tenant.vo.tenant.TenantSaveReqVO;
-import com.iailab.module.system.dal.dataobject.permission.MenuDO;
-import com.iailab.module.system.dal.dataobject.permission.RoleDO;
-import com.iailab.module.system.dal.dataobject.tenant.TenantDO;
-import com.iailab.module.system.dal.dataobject.tenant.TenantPackageDO;
-import com.iailab.module.system.dal.mysql.tenant.TenantMapper;
-import com.iailab.module.system.enums.permission.RoleCodeEnum;
-import com.iailab.module.system.enums.permission.RoleTypeEnum;
-import com.iailab.module.system.service.permission.MenuService;
-import com.iailab.module.system.service.permission.PermissionService;
-import com.iailab.module.system.service.permission.RoleService;
-import com.iailab.module.system.service.tenant.handler.TenantInfoHandler;
-import com.iailab.module.system.service.tenant.handler.TenantMenuHandler;
-import com.iailab.module.system.service.user.AdminUserService;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.context.annotation.Import;
-
-import javax.annotation.Resource;
-import java.time.LocalDateTime;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import static com.iailab.framework.common.util.collection.SetUtils.asSet;
-import static com.iailab.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
-import static com.iailab.framework.common.util.date.LocalDateTimeUtils.buildTime;
-import static com.iailab.framework.common.util.object.ObjectUtils.cloneIgnoreId;
-import static com.iailab.framework.test.core.util.AssertUtils.assertPojoEquals;
-import static com.iailab.framework.test.core.util.AssertUtils.assertServiceException;
-import static com.iailab.framework.test.core.util.RandomUtils.*;
-import static com.iailab.module.system.dal.dataobject.tenant.TenantDO.PACKAGE_ID_SYSTEM;
-import static com.iailab.module.system.enums.ErrorCodeConstants.*;
-import static java.util.Arrays.asList;
-import static java.util.Collections.singleton;
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.*;
-import static org.mockito.Mockito.*;
-
-/**
- * {@link TenantServiceImpl} 的单元测试类
- *
- * @author iailab
- */
-@Import(TenantServiceImpl.class)
-public class TenantServiceImplTest extends BaseDbUnitTest {
-
-    @Resource
-    private TenantServiceImpl tenantService;
-
-    @Resource
-    private TenantMapper tenantMapper;
-
-    @MockBean
-    private TenantProperties tenantProperties;
-    @MockBean
-    private TenantPackageService tenantPackageService;
-    @MockBean
-    private AdminUserService userService;
-    @MockBean
-    private RoleService roleService;
-    @MockBean
-    private MenuService menuService;
-    @MockBean
-    private PermissionService permissionService;
-
-    @BeforeEach
-    public void setUp() {
-        // 清理租户上下文
-        TenantContextHolder.clear();
-    }
-
-    @Test
-    public void testGetTenantIdList() {
-        // mock 数据
-        TenantDO tenant = randomPojo(TenantDO.class, o -> o.setId(1L));
-        tenantMapper.insert(tenant);
-
-        // 调用,并断言业务异常
-        List<Long> result = tenantService.getTenantIdList();
-        assertEquals(Collections.singletonList(1L), result);
-    }
-
-    @Test
-    public void testValidTenant_notExists() {
-        assertServiceException(() -> tenantService.validTenant(randomLongId()), TENANT_NOT_EXISTS);
-    }
-
-    @Test
-    public void testValidTenant_disable() {
-        // mock 数据
-        TenantDO tenant = randomPojo(TenantDO.class, o -> o.setId(1L).setStatus(CommonStatusEnum.DISABLE.getStatus()));
-        tenantMapper.insert(tenant);
-
-        // 调用,并断言业务异常
-        assertServiceException(() -> tenantService.validTenant(1L), TENANT_DISABLE, tenant.getName());
-    }
-
-    @Test
-    public void testValidTenant_expired() {
-        // mock 数据
-        TenantDO tenant = randomPojo(TenantDO.class, o -> o.setId(1L).setStatus(CommonStatusEnum.ENABLE.getStatus())
-                .setExpireTime(buildTime(2020, 2, 2)));
-        tenantMapper.insert(tenant);
-
-        // 调用,并断言业务异常
-        assertServiceException(() -> tenantService.validTenant(1L), TENANT_EXPIRE, tenant.getName());
-    }
-
-    @Test
-    public void testValidTenant_success() {
-        // mock 数据
-        TenantDO tenant = randomPojo(TenantDO.class, o -> o.setId(1L).setStatus(CommonStatusEnum.ENABLE.getStatus())
-                .setExpireTime(LocalDateTime.now().plusDays(1)));
-        tenantMapper.insert(tenant);
-
-        // 调用,并断言业务异常
-        tenantService.validTenant(1L);
-    }
-
-    @Test
-    public void testCreateTenant() {
-        // mock 套餐 100L
-        TenantPackageDO tenantPackage = randomPojo(TenantPackageDO.class, o -> o.setId(100L));
-        when(tenantPackageService.validTenantPackage(eq(100L))).thenReturn(tenantPackage);
-        // mock 角色 200L
-        when(roleService.createRole(argThat(role -> {
-            assertEquals(RoleCodeEnum.TENANT_ADMIN.getName(), role.getName());
-            assertEquals(RoleCodeEnum.TENANT_ADMIN.getCode(), role.getCode());
-            assertEquals(0, role.getSort());
-            assertEquals("系统自动生成", role.getRemark());
-            return true;
-        }), eq(RoleTypeEnum.SYSTEM.getType()))).thenReturn(200L);
-        // mock 用户 300L
-        when(userService.createUser(argThat(user -> {
-            assertEquals("yunai", user.getUsername());
-            assertEquals("yuanma", user.getPassword());
-            assertEquals("平台", user.getNickname());
-            assertEquals("15601691300", user.getMobile());
-            return true;
-        }))).thenReturn(300L);
-
-        // 准备参数
-        TenantSaveReqVO reqVO = randomPojo(TenantSaveReqVO.class, o -> {
-            o.setContactName("平台");
-            o.setContactMobile("15601691300");
-            o.setPackageId(100L);
-            o.setStatus(randomCommonStatus());
-            o.setWebsite("https://www.baidu.com");
-            o.setUsername("yunai");
-            o.setPassword("yuanma");
-        }).setId(null); // 设置为 null,方便后面校验
-
-        // 调用
-        Long tenantId = tenantService.createTenant(reqVO);
-        // 断言
-        assertNotNull(tenantId);
-        // 校验记录的属性是否正确
-        TenantDO tenant = tenantMapper.selectById(tenantId);
-        assertPojoEquals(reqVO, tenant, "id");
-        assertEquals(300L, tenant.getContactUserId());
-        // verify 分配权限
-        verify(permissionService).assignRoleMenu(eq(200L), same(tenantPackage.getMenuIds()));
-        // verify 分配角色
-        verify(permissionService).assignUserRole(eq(300L), eq(singleton(200L)));
-    }
-
-    @Test
-    public void testUpdateTenant_success() {
-        // mock 数据
-        TenantDO dbTenant = randomPojo(TenantDO.class, o -> o.setStatus(randomCommonStatus()));
-        tenantMapper.insert(dbTenant);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        TenantSaveReqVO reqVO = randomPojo(TenantSaveReqVO.class, o -> {
-            o.setId(dbTenant.getId()); // 设置更新的 ID
-            o.setStatus(randomCommonStatus());
-            o.setWebsite(randomString());
-        });
-
-        // mock 套餐
-        TenantPackageDO tenantPackage = randomPojo(TenantPackageDO.class,
-                o -> o.setMenuIds(asSet(200L, 201L)));
-        when(tenantPackageService.validTenantPackage(eq(reqVO.getPackageId()))).thenReturn(tenantPackage);
-        // mock 所有角色
-        RoleDO role100 = randomPojo(RoleDO.class, o -> o.setId(100L).setCode(RoleCodeEnum.TENANT_ADMIN.getCode()));
-        role100.setTenantId(dbTenant.getId());
-        RoleDO role101 = randomPojo(RoleDO.class, o -> o.setId(101L));
-        role101.setTenantId(dbTenant.getId());
-        when(roleService.getRoleList()).thenReturn(asList(role100, role101));
-        // mock 每个角色的权限
-        when(permissionService.getRoleMenuListByRoleId(eq(101L))).thenReturn(asSet(201L, 202L));
-
-        // 调用
-        tenantService.updateTenant(reqVO);
-        // 校验是否更新正确
-        TenantDO tenant = tenantMapper.selectById(reqVO.getId()); // 获取最新的
-        assertPojoEquals(reqVO, tenant);
-        // verify 设置角色权限
-        verify(permissionService).assignRoleMenu(eq(100L), eq(asSet(200L, 201L)));
-        verify(permissionService).assignRoleMenu(eq(101L), eq(asSet(201L)));
-    }
-
-    @Test
-    public void testUpdateTenant_notExists() {
-        // 准备参数
-        TenantSaveReqVO reqVO = randomPojo(TenantSaveReqVO.class);
-
-        // 调用, 并断言异常
-        assertServiceException(() -> tenantService.updateTenant(reqVO), TENANT_NOT_EXISTS);
-    }
-
-    @Test
-    public void testUpdateTenant_system() {
-        // mock 数据
-        TenantDO dbTenant = randomPojo(TenantDO.class, o -> o.setPackageId(PACKAGE_ID_SYSTEM));
-        tenantMapper.insert(dbTenant);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        TenantSaveReqVO reqVO = randomPojo(TenantSaveReqVO.class, o -> {
-            o.setId(dbTenant.getId()); // 设置更新的 ID
-        });
-
-        // 调用,校验业务异常
-        assertServiceException(() -> tenantService.updateTenant(reqVO), TENANT_CAN_NOT_UPDATE_SYSTEM);
-    }
-
-    @Test
-    public void testDeleteTenant_success() {
-        // mock 数据
-        TenantDO dbTenant = randomPojo(TenantDO.class,
-                o -> o.setStatus(randomCommonStatus()));
-        tenantMapper.insert(dbTenant);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        Long id = dbTenant.getId();
-
-        // 调用
-        tenantService.deleteTenant(id);
-        // 校验数据不存在了
-        assertNull(tenantMapper.selectById(id));
-    }
-
-    @Test
-    public void testDeleteTenant_notExists() {
-        // 准备参数
-        Long id = randomLongId();
-
-        // 调用, 并断言异常
-        assertServiceException(() -> tenantService.deleteTenant(id), TENANT_NOT_EXISTS);
-    }
-
-    @Test
-    public void testDeleteTenant_system() {
-        // mock 数据
-        TenantDO dbTenant = randomPojo(TenantDO.class, o -> o.setPackageId(PACKAGE_ID_SYSTEM));
-        tenantMapper.insert(dbTenant);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        Long id = dbTenant.getId();
-
-        // 调用, 并断言异常
-        assertServiceException(() -> tenantService.deleteTenant(id), TENANT_CAN_NOT_UPDATE_SYSTEM);
-    }
-
-    @Test
-    public void testGetTenant() {
-        // mock 数据
-        TenantDO dbTenant = randomPojo(TenantDO.class);
-        tenantMapper.insert(dbTenant);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        Long id = dbTenant.getId();
-
-        // 调用
-        TenantDO result = tenantService.getTenant(id);
-        // 校验存在
-        assertPojoEquals(result, dbTenant);
-    }
-
-    @Test
-    public void testGetTenantPage() {
-        // mock 数据
-        TenantDO dbTenant = randomPojo(TenantDO.class, o -> { // 等会查询到
-            o.setName("iailab");
-            o.setContactName("iailab");
-            o.setContactMobile("15601691300");
-            o.setStatus(CommonStatusEnum.ENABLE.getStatus());
-            o.setCreateTime(buildTime(2020, 12, 12));
-        });
-        tenantMapper.insert(dbTenant);
-        // 测试 name 不匹配
-        tenantMapper.insert(cloneIgnoreId(dbTenant, o -> o.setName(randomString())));
-        // 测试 contactName 不匹配
-        tenantMapper.insert(cloneIgnoreId(dbTenant, o -> o.setContactName(randomString())));
-        // 测试 contactMobile 不匹配
-        tenantMapper.insert(cloneIgnoreId(dbTenant, o -> o.setContactMobile(randomString())));
-        // 测试 status 不匹配
-        tenantMapper.insert(cloneIgnoreId(dbTenant, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
-        // 测试 createTime 不匹配
-        tenantMapper.insert(cloneIgnoreId(dbTenant, o -> o.setCreateTime(buildTime(2021, 12, 12))));
-        // 准备参数
-        TenantPageReqVO reqVO = new TenantPageReqVO();
-        reqVO.setName("平台");
-        reqVO.setContactName("艿");
-        reqVO.setContactMobile("1560");
-        reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
-        reqVO.setCreateTime(buildBetweenTime(2020, 12, 1, 2020, 12, 24));
-
-        // 调用
-        PageResult<TenantDO> pageResult = tenantService.getTenantPage(reqVO);
-        // 断言
-        assertEquals(1, pageResult.getTotal());
-        assertEquals(1, pageResult.getList().size());
-        assertPojoEquals(dbTenant, pageResult.getList().get(0));
-    }
-
-    @Test
-    public void testGetTenantByName() {
-        // mock 数据
-        TenantDO dbTenant = randomPojo(TenantDO.class, o -> o.setName("平台"));
-        tenantMapper.insert(dbTenant);// @Sql: 先插入出一条存在的数据
-
-        // 调用
-        TenantDO result = tenantService.getTenantByName("平台");
-        // 校验存在
-        assertPojoEquals(result, dbTenant);
-    }
-
-    @Test
-    public void testGetTenantByWebsite() {
-        // mock 数据
-        TenantDO dbTenant = randomPojo(TenantDO.class, o -> o.setWebsite("https://www.baidu.com"));
-        tenantMapper.insert(dbTenant);// @Sql: 先插入出一条存在的数据
-
-        // 调用
-        TenantDO result = tenantService.getTenantByWebsite("https://www.baidu.com");
-        // 校验存在
-        assertPojoEquals(result, dbTenant);
-    }
-
-    @Test
-    public void testGetTenantListByPackageId() {
-        // mock 数据
-        TenantDO dbTenant1 = randomPojo(TenantDO.class, o -> o.setPackageId(1L));
-        tenantMapper.insert(dbTenant1);// @Sql: 先插入出一条存在的数据
-        TenantDO dbTenant2 = randomPojo(TenantDO.class, o -> o.setPackageId(2L));
-        tenantMapper.insert(dbTenant2);// @Sql: 先插入出一条存在的数据
-
-        // 调用
-        List<TenantDO> result = tenantService.getTenantListByPackageId(1L);
-        assertEquals(1, result.size());
-        assertPojoEquals(dbTenant1, result.get(0));
-    }
-
-    @Test
-    public void testGetTenantCountByPackageId() {
-        // mock 数据
-        TenantDO dbTenant1 = randomPojo(TenantDO.class, o -> o.setPackageId(1L));
-        tenantMapper.insert(dbTenant1);// @Sql: 先插入出一条存在的数据
-        TenantDO dbTenant2 = randomPojo(TenantDO.class, o -> o.setPackageId(2L));
-        tenantMapper.insert(dbTenant2);// @Sql: 先插入出一条存在的数据
-
-        // 调用
-        Long count = tenantService.getTenantCountByPackageId(1L);
-        assertEquals(1, count);
-    }
-
-    @Test
-    public void testHandleTenantInfo_disable() {
-        // 准备参数
-        TenantInfoHandler handler = mock(TenantInfoHandler.class);
-        // mock 禁用
-        when(tenantProperties.getEnable()).thenReturn(false);
-
-        // 调用
-        tenantService.handleTenantInfo(handler);
-        // 断言
-        verify(handler, never()).handle(any());
-    }
-
-    @Test
-    public void testHandleTenantInfo_success() {
-        // 准备参数
-        TenantInfoHandler handler = mock(TenantInfoHandler.class);
-        // mock 未禁用
-        when(tenantProperties.getEnable()).thenReturn(true);
-        // mock 租户
-        TenantDO dbTenant = randomPojo(TenantDO.class);
-        tenantMapper.insert(dbTenant);// @Sql: 先插入出一条存在的数据
-        TenantContextHolder.setTenantId(dbTenant.getId());
-
-        // 调用
-        tenantService.handleTenantInfo(handler);
-        // 断言
-        verify(handler).handle(argThat(argument -> {
-            assertPojoEquals(dbTenant, argument);
-            return true;
-        }));
-    }
-
-    @Test
-    public void testHandleTenantMenu_disable() {
-        // 准备参数
-        TenantMenuHandler handler = mock(TenantMenuHandler.class);
-        // mock 禁用
-        when(tenantProperties.getEnable()).thenReturn(false);
-
-        // 调用
-        tenantService.handleTenantMenu(handler);
-        // 断言
-        verify(handler, never()).handle(any());
-    }
-
-    @Test // 系统租户的情况
-    public void testHandleTenantMenu_system() {
-        // 准备参数
-        TenantMenuHandler handler = mock(TenantMenuHandler.class);
-        // mock 未禁用
-        when(tenantProperties.getEnable()).thenReturn(true);
-        // mock 租户
-        TenantDO dbTenant = randomPojo(TenantDO.class, o -> o.setPackageId(PACKAGE_ID_SYSTEM));
-        tenantMapper.insert(dbTenant);// @Sql: 先插入出一条存在的数据
-        TenantContextHolder.setTenantId(dbTenant.getId());
-        // mock 菜单
-        when(menuService.getMenuList()).thenReturn(Arrays.asList(randomPojo(MenuDO.class, o -> o.setId(100L)),
-                randomPojo(MenuDO.class, o -> o.setId(101L))));
-
-        // 调用
-        tenantService.handleTenantMenu(handler);
-        // 断言
-        verify(handler).handle(asSet(100L, 101L));
-    }
-
-    @Test // 普通租户的情况
-    public void testHandleTenantMenu_normal() {
-        // 准备参数
-        TenantMenuHandler handler = mock(TenantMenuHandler.class);
-        // mock 未禁用
-        when(tenantProperties.getEnable()).thenReturn(true);
-        // mock 租户
-        TenantDO dbTenant = randomPojo(TenantDO.class, o -> o.setPackageId(200L));
-        tenantMapper.insert(dbTenant);// @Sql: 先插入出一条存在的数据
-        TenantContextHolder.setTenantId(dbTenant.getId());
-        // mock 菜单
-        when(tenantPackageService.getTenantPackage(eq(200L))).thenReturn(randomPojo(TenantPackageDO.class,
-                o -> o.setMenuIds(asSet(100L, 101L))));
-
-        // 调用
-        tenantService.handleTenantMenu(handler);
-        // 断言
-        verify(handler).handle(asSet(100L, 101L));
-    }
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/user/AdminUserServiceImplTest.java b/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/user/AdminUserServiceImplTest.java
deleted file mode 100644
index 9b40675..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/test/java/com/iailab/module/system/service/user/AdminUserServiceImplTest.java
+++ /dev/null
@@ -1,765 +0,0 @@
-package com.iailab.module.system.service.user;
-
-import cn.hutool.core.util.RandomUtil;
-import com.iailab.framework.common.enums.CommonStatusEnum;
-import com.iailab.framework.common.exception.ServiceException;
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.framework.common.util.collection.ArrayUtils;
-import com.iailab.framework.common.util.collection.CollectionUtils;
-import com.iailab.framework.test.core.ut.BaseDbUnitTest;
-import com.iailab.module.infra.api.file.FileApi;
-import com.iailab.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO;
-import com.iailab.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO;
-import com.iailab.module.system.controller.admin.user.vo.user.UserImportExcelVO;
-import com.iailab.module.system.controller.admin.user.vo.user.UserImportRespVO;
-import com.iailab.module.system.controller.admin.user.vo.user.UserPageReqVO;
-import com.iailab.module.system.controller.admin.user.vo.user.UserSaveReqVO;
-import com.iailab.module.system.dal.dataobject.dept.DeptDO;
-import com.iailab.module.system.dal.dataobject.dept.PostDO;
-import com.iailab.module.system.dal.dataobject.dept.UserPostDO;
-import com.iailab.module.system.dal.dataobject.tenant.TenantDO;
-import com.iailab.module.system.dal.dataobject.user.AdminUserDO;
-import com.iailab.module.system.dal.mysql.dept.UserPostMapper;
-import com.iailab.module.system.dal.mysql.user.AdminUserMapper;
-import com.iailab.module.system.enums.common.SexEnum;
-import com.iailab.module.system.service.dept.DeptService;
-import com.iailab.module.system.service.dept.PostService;
-import com.iailab.module.system.service.permission.PermissionService;
-import com.iailab.module.system.service.tenant.TenantService;
-import org.junit.jupiter.api.Test;
-import org.mockito.stubbing.Answer;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.context.annotation.Import;
-import org.springframework.security.crypto.password.PasswordEncoder;
-
-import javax.annotation.Resource;
-import java.io.ByteArrayInputStream;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.function.Consumer;
-
-import static cn.hutool.core.util.RandomUtil.randomBytes;
-import static cn.hutool.core.util.RandomUtil.randomEle;
-import static com.iailab.framework.common.util.collection.SetUtils.asSet;
-import static com.iailab.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
-import static com.iailab.framework.common.util.date.LocalDateTimeUtils.buildTime;
-import static com.iailab.framework.common.util.object.ObjectUtils.cloneIgnoreId;
-import static com.iailab.framework.test.core.util.AssertUtils.assertPojoEquals;
-import static com.iailab.framework.test.core.util.AssertUtils.assertServiceException;
-import static com.iailab.framework.test.core.util.RandomUtils.*;
-import static com.iailab.module.system.enums.ErrorCodeConstants.*;
-import static java.util.Collections.singleton;
-import static java.util.Collections.singletonList;
-import static org.assertj.core.util.Lists.newArrayList;
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.*;
-import static org.mockito.Mockito.*;
-
-@Import(AdminUserServiceImpl.class)
-public class AdminUserServiceImplTest extends BaseDbUnitTest {
-
-    @Resource
-    private AdminUserServiceImpl userService;
-
-    @Resource
-    private AdminUserMapper userMapper;
-    @Resource
-    private UserPostMapper userPostMapper;
-
-    @MockBean
-    private DeptService deptService;
-    @MockBean
-    private PostService postService;
-    @MockBean
-    private PermissionService permissionService;
-    @MockBean
-    private PasswordEncoder passwordEncoder;
-    @MockBean
-    private TenantService tenantService;
-    @MockBean
-    private FileApi fileApi;
-
-    @Test
-    public void testCreatUser_success() {
-        // 准备参数
-        UserSaveReqVO reqVO = randomPojo(UserSaveReqVO.class, o -> {
-            o.setSex(RandomUtil.randomEle(SexEnum.values()).getSex());
-            o.setMobile(randomString());
-            o.setPostIds(asSet(1L, 2L));
-        }).setId(null); // 避免 id 被赋值
-        // mock 账户额度充足
-        TenantDO tenant = randomPojo(TenantDO.class, o -> o.setAccountCount(1));
-        doNothing().when(tenantService).handleTenantInfo(argThat(handler -> {
-            handler.handle(tenant);
-            return true;
-        }));
-        // mock deptService 的方法
-        DeptDO dept = randomPojo(DeptDO.class, o -> {
-            o.setId(reqVO.getDeptId());
-            o.setStatus(CommonStatusEnum.ENABLE.getStatus());
-        });
-        when(deptService.getDept(eq(dept.getId()))).thenReturn(dept);
-        // mock postService 的方法
-        List<PostDO> posts = CollectionUtils.convertList(reqVO.getPostIds(), postId ->
-                randomPojo(PostDO.class, o -> {
-                    o.setId(postId);
-                    o.setStatus(CommonStatusEnum.ENABLE.getStatus());
-                }));
-        when(postService.getPostList(eq(reqVO.getPostIds()), isNull())).thenReturn(posts);
-        // mock passwordEncoder 的方法
-        when(passwordEncoder.encode(eq(reqVO.getPassword()))).thenReturn("iailabyuanma");
-
-        // 调用
-        Long userId = userService.createUser(reqVO);
-        // 断言
-        AdminUserDO user = userMapper.selectById(userId);
-        assertPojoEquals(reqVO, user, "password", "id");
-        assertEquals("iailabyuanma", user.getPassword());
-        assertEquals(CommonStatusEnum.ENABLE.getStatus(), user.getStatus());
-        // 断言关联岗位
-        List<UserPostDO> userPosts = userPostMapper.selectListByUserId(user.getId());
-        assertEquals(1L, userPosts.get(0).getPostId());
-        assertEquals(2L, userPosts.get(1).getPostId());
-    }
-
-    @Test
-    public void testCreatUser_max() {
-        // 准备参数
-        UserSaveReqVO reqVO = randomPojo(UserSaveReqVO.class);
-        // mock 账户额度不足
-        TenantDO tenant = randomPojo(TenantDO.class, o -> o.setAccountCount(-1));
-        doNothing().when(tenantService).handleTenantInfo(argThat(handler -> {
-            handler.handle(tenant);
-            return true;
-        }));
-
-        // 调用,并断言异常
-        assertServiceException(() -> userService.createUser(reqVO), USER_COUNT_MAX, -1);
-    }
-
-    @Test
-    public void testUpdateUser_success() {
-        // mock 数据
-        AdminUserDO dbUser = randomAdminUserDO(o -> o.setPostIds(asSet(1L, 2L)));
-        userMapper.insert(dbUser);
-        userPostMapper.insert(new UserPostDO().setUserId(dbUser.getId()).setPostId(1L));
-        userPostMapper.insert(new UserPostDO().setUserId(dbUser.getId()).setPostId(2L));
-        // 准备参数
-        UserSaveReqVO reqVO = randomPojo(UserSaveReqVO.class, o -> {
-            o.setId(dbUser.getId());
-            o.setSex(RandomUtil.randomEle(SexEnum.values()).getSex());
-            o.setMobile(randomString());
-            o.setPostIds(asSet(2L, 3L));
-        });
-        // mock deptService 的方法
-        DeptDO dept = randomPojo(DeptDO.class, o -> {
-            o.setId(reqVO.getDeptId());
-            o.setStatus(CommonStatusEnum.ENABLE.getStatus());
-        });
-        when(deptService.getDept(eq(dept.getId()))).thenReturn(dept);
-        // mock postService 的方法
-        List<PostDO> posts = CollectionUtils.convertList(reqVO.getPostIds(), postId ->
-                randomPojo(PostDO.class, o -> {
-                    o.setId(postId);
-                    o.setStatus(CommonStatusEnum.ENABLE.getStatus());
-                }));
-        when(postService.getPostList(eq(reqVO.getPostIds()), isNull())).thenReturn(posts);
-
-        // 调用
-        userService.updateUser(reqVO);
-        // 断言
-        AdminUserDO user = userMapper.selectById(reqVO.getId());
-        assertPojoEquals(reqVO, user, "password");
-        // 断言关联岗位
-        List<UserPostDO> userPosts = userPostMapper.selectListByUserId(user.getId());
-        assertEquals(2L, userPosts.get(0).getPostId());
-        assertEquals(3L, userPosts.get(1).getPostId());
-    }
-
-    @Test
-    public void testUpdateUserLogin() {
-        // mock 数据
-        AdminUserDO user = randomAdminUserDO(o -> o.setLoginDate(null));
-        userMapper.insert(user);
-        // 准备参数
-        Long id = user.getId();
-        String loginIp = randomString();
-
-        // 调用
-        userService.updateUserLogin(id, loginIp);
-        // 断言
-        AdminUserDO dbUser = userMapper.selectById(id);
-        assertEquals(loginIp, dbUser.getLoginIp());
-        assertNotNull(dbUser.getLoginDate());
-    }
-
-    @Test
-    public void testUpdateUserProfile_success() {
-        // mock 数据
-        AdminUserDO dbUser = randomAdminUserDO();
-        userMapper.insert(dbUser);
-        // 准备参数
-        Long userId = dbUser.getId();
-        UserProfileUpdateReqVO reqVO = randomPojo(UserProfileUpdateReqVO.class, o -> {
-            o.setMobile(randomString());
-            o.setSex(RandomUtil.randomEle(SexEnum.values()).getSex());
-        });
-
-        // 调用
-        userService.updateUserProfile(userId, reqVO);
-        // 断言
-        AdminUserDO user = userMapper.selectById(userId);
-        assertPojoEquals(reqVO, user);
-    }
-
-    @Test
-    public void testUpdateUserPassword_success() {
-        // mock 数据
-        AdminUserDO dbUser = randomAdminUserDO(o -> o.setPassword("encode:tudou"));
-        userMapper.insert(dbUser);
-        // 准备参数
-        Long userId = dbUser.getId();
-        UserProfileUpdatePasswordReqVO reqVO = randomPojo(UserProfileUpdatePasswordReqVO.class, o -> {
-            o.setOldPassword("tudou");
-            o.setNewPassword("yuanma");
-        });
-        // mock 方法
-        when(passwordEncoder.encode(anyString())).then(
-                (Answer<String>) invocationOnMock -> "encode:" + invocationOnMock.getArgument(0));
-        when(passwordEncoder.matches(eq(reqVO.getOldPassword()), eq(dbUser.getPassword()))).thenReturn(true);
-
-        // 调用
-        userService.updateUserPassword(userId, reqVO);
-        // 断言
-        AdminUserDO user = userMapper.selectById(userId);
-        assertEquals("encode:yuanma", user.getPassword());
-    }
-
-    @Test
-    public void testUpdateUserAvatar_success() throws Exception {
-        // mock 数据
-        AdminUserDO dbUser = randomAdminUserDO();
-        userMapper.insert(dbUser);
-        // 准备参数
-        Long userId = dbUser.getId();
-        byte[] avatarFileBytes = randomBytes(10);
-        ByteArrayInputStream avatarFile = new ByteArrayInputStream(avatarFileBytes);
-        // mock 方法
-        String avatar = randomString();
-        when(fileApi.createFile(eq( avatarFileBytes))).thenReturn(avatar);
-
-        // 调用
-        userService.updateUserAvatar(userId, avatarFile);
-        // 断言
-        AdminUserDO user = userMapper.selectById(userId);
-        assertEquals(avatar, user.getAvatar());
-    }
-
-    @Test
-    public void testUpdateUserPassword02_success() {
-        // mock 数据
-        AdminUserDO dbUser = randomAdminUserDO();
-        userMapper.insert(dbUser);
-        // 准备参数
-        Long userId = dbUser.getId();
-        String password = "iailab";
-        // mock 方法
-        when(passwordEncoder.encode(anyString())).then(
-                (Answer<String>) invocationOnMock -> "encode:" + invocationOnMock.getArgument(0));
-
-        // 调用
-        userService.updateUserPassword(userId, password);
-        // 断言
-        AdminUserDO user = userMapper.selectById(userId);
-        assertEquals("encode:" + password, user.getPassword());
-    }
-
-    @Test
-    public void testUpdateUserStatus() {
-        // mock 数据
-        AdminUserDO dbUser = randomAdminUserDO();
-        userMapper.insert(dbUser);
-        // 准备参数
-        Long userId = dbUser.getId();
-        Integer status = randomCommonStatus();
-
-        // 调用
-        userService.updateUserStatus(userId, status);
-        // 断言
-        AdminUserDO user = userMapper.selectById(userId);
-        assertEquals(status, user.getStatus());
-    }
-
-    @Test
-    public void testDeleteUser_success(){
-        // mock 数据
-        AdminUserDO dbUser = randomAdminUserDO();
-        userMapper.insert(dbUser);
-        // 准备参数
-        Long userId = dbUser.getId();
-
-        // 调用数据
-        userService.deleteUser(userId);
-        // 校验结果
-        assertNull(userMapper.selectById(userId));
-        // 校验调用次数
-        verify(permissionService, times(1)).processUserDeleted(eq(userId));
-    }
-
-    @Test
-    public void testGetUserByUsername() {
-        // mock 数据
-        AdminUserDO dbUser = randomAdminUserDO();
-        userMapper.insert(dbUser);
-        // 准备参数
-        String username = dbUser.getUsername();
-
-        // 调用
-        AdminUserDO user = userService.getUserByUsername(username);
-        // 断言
-        assertPojoEquals(dbUser, user);
-    }
-
-    @Test
-    public void testGetUserByMobile() {
-        // mock 数据
-        AdminUserDO dbUser = randomAdminUserDO();
-        userMapper.insert(dbUser);
-        // 准备参数
-        String mobile = dbUser.getMobile();
-
-        // 调用
-        AdminUserDO user = userService.getUserByMobile(mobile);
-        // 断言
-        assertPojoEquals(dbUser, user);
-    }
-
-    @Test
-    public void testGetUserPage() {
-        // mock 数据
-        AdminUserDO dbUser = initGetUserPageData();
-        // 准备参数
-        UserPageReqVO reqVO = new UserPageReqVO();
-        reqVO.setUsername("tu");
-        reqVO.setMobile("1560");
-        reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
-        reqVO.setCreateTime(buildBetweenTime(2020, 12, 1, 2020, 12, 24));
-        reqVO.setDeptId(1L); // 其中,1L 是 2L 的父部门
-        // mock 方法
-        List<DeptDO> deptList = newArrayList(randomPojo(DeptDO.class, o -> o.setId(2L)));
-        when(deptService.getChildDeptList(eq(reqVO.getDeptId()))).thenReturn(deptList);
-
-        // 调用
-        PageResult<AdminUserDO> pageResult = userService.getUserPage(reqVO);
-        // 断言
-        assertEquals(1, pageResult.getTotal());
-        assertEquals(1, pageResult.getList().size());
-        assertPojoEquals(dbUser, pageResult.getList().get(0));
-    }
-
-    /**
-     * 初始化 getUserPage 方法的测试数据
-     */
-    private AdminUserDO initGetUserPageData() {
-        // mock 数据
-        AdminUserDO dbUser = randomAdminUserDO(o -> { // 等会查询到
-            o.setUsername("tudou");
-            o.setMobile("15601691300");
-            o.setStatus(CommonStatusEnum.ENABLE.getStatus());
-            o.setCreateTime(buildTime(2020, 12, 12));
-            o.setDeptId(2L);
-        });
-        userMapper.insert(dbUser);
-        // 测试 username 不匹配
-        userMapper.insert(cloneIgnoreId(dbUser, o -> o.setUsername("dou")));
-        // 测试 mobile 不匹配
-        userMapper.insert(cloneIgnoreId(dbUser, o -> o.setMobile("18818260888")));
-        // 测试 status 不匹配
-        userMapper.insert(cloneIgnoreId(dbUser, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
-        // 测试 createTime 不匹配
-        userMapper.insert(cloneIgnoreId(dbUser, o -> o.setCreateTime(buildTime(2020, 11, 11))));
-        // 测试 dept 不匹配
-        userMapper.insert(cloneIgnoreId(dbUser, o -> o.setDeptId(0L)));
-        return dbUser;
-    }
-
-    @Test
-    public void testGetUser() {
-        // mock 数据
-        AdminUserDO dbUser = randomAdminUserDO();
-        userMapper.insert(dbUser);
-        // 准备参数
-        Long userId = dbUser.getId();
-
-        // 调用
-        AdminUserDO user = userService.getUser(userId);
-        // 断言
-        assertPojoEquals(dbUser, user);
-    }
-
-    @Test
-    public void testGetUserListByDeptIds() {
-        // mock 数据
-        AdminUserDO dbUser = randomAdminUserDO(o -> o.setDeptId(1L));
-        userMapper.insert(dbUser);
-        // 测试 deptId 不匹配
-        userMapper.insert(cloneIgnoreId(dbUser, o -> o.setDeptId(2L)));
-        // 准备参数
-        Collection<Long> deptIds = singleton(1L);
-
-        // 调用
-        List<AdminUserDO> list = userService.getUserListByDeptIds(deptIds);
-        // 断言
-        assertEquals(1, list.size());
-        assertEquals(dbUser, list.get(0));
-    }
-
-    /**
-     * 情况一,校验不通过,导致插入失败
-     */
-    @Test
-    public void testImportUserList_01() {
-        // 准备参数
-        UserImportExcelVO importUser = randomPojo(UserImportExcelVO.class, o -> {
-        });
-        // mock 方法,模拟失败
-        doThrow(new ServiceException(DEPT_NOT_FOUND)).when(deptService).validateDeptList(any());
-
-        // 调用
-        UserImportRespVO respVO = userService.importUserList(newArrayList(importUser), true);
-        // 断言
-        assertEquals(0, respVO.getCreateUsernames().size());
-        assertEquals(0, respVO.getUpdateUsernames().size());
-        assertEquals(1, respVO.getFailureUsernames().size());
-        assertEquals(DEPT_NOT_FOUND.getMsg(), respVO.getFailureUsernames().get(importUser.getUsername()));
-    }
-
-    /**
-     * 情况二,不存在,进行插入
-     */
-    @Test
-    public void testImportUserList_02() {
-        // 准备参数
-        UserImportExcelVO importUser = randomPojo(UserImportExcelVO.class, o -> {
-            o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围
-            o.setSex(randomEle(SexEnum.values()).getSex()); // 保证 sex 的范围
-        });
-        // mock deptService 的方法
-        DeptDO dept = randomPojo(DeptDO.class, o -> {
-            o.setId(importUser.getDeptId());
-            o.setStatus(CommonStatusEnum.ENABLE.getStatus());
-        });
-        when(deptService.getDept(eq(dept.getId()))).thenReturn(dept);
-        // mock passwordEncoder 的方法
-        when(passwordEncoder.encode(eq("iailabyuanma"))).thenReturn("java");
-
-        // 调用
-        UserImportRespVO respVO = userService.importUserList(newArrayList(importUser), true);
-        // 断言
-        assertEquals(1, respVO.getCreateUsernames().size());
-        AdminUserDO user = userMapper.selectByUsername(respVO.getCreateUsernames().get(0));
-        assertPojoEquals(importUser, user);
-        assertEquals("java", user.getPassword());
-        assertEquals(0, respVO.getUpdateUsernames().size());
-        assertEquals(0, respVO.getFailureUsernames().size());
-    }
-
-    /**
-     * 情况三,存在,但是不强制更新
-     */
-    @Test
-    public void testImportUserList_03() {
-        // mock 数据
-        AdminUserDO dbUser = randomAdminUserDO();
-        userMapper.insert(dbUser);
-        // 准备参数
-        UserImportExcelVO importUser = randomPojo(UserImportExcelVO.class, o -> {
-            o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围
-            o.setSex(randomEle(SexEnum.values()).getSex()); // 保证 sex 的范围
-            o.setUsername(dbUser.getUsername());
-        });
-        // mock deptService 的方法
-        DeptDO dept = randomPojo(DeptDO.class, o -> {
-            o.setId(importUser.getDeptId());
-            o.setStatus(CommonStatusEnum.ENABLE.getStatus());
-        });
-        when(deptService.getDept(eq(dept.getId()))).thenReturn(dept);
-
-        // 调用
-        UserImportRespVO respVO = userService.importUserList(newArrayList(importUser), false);
-        // 断言
-        assertEquals(0, respVO.getCreateUsernames().size());
-        assertEquals(0, respVO.getUpdateUsernames().size());
-        assertEquals(1, respVO.getFailureUsernames().size());
-        assertEquals(USER_USERNAME_EXISTS.getMsg(), respVO.getFailureUsernames().get(importUser.getUsername()));
-    }
-
-    /**
-     * 情况四,存在,强制更新
-     */
-    @Test
-    public void testImportUserList_04() {
-        // mock 数据
-        AdminUserDO dbUser = randomAdminUserDO();
-        userMapper.insert(dbUser);
-        // 准备参数
-        UserImportExcelVO importUser = randomPojo(UserImportExcelVO.class, o -> {
-            o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围
-            o.setSex(randomEle(SexEnum.values()).getSex()); // 保证 sex 的范围
-            o.setUsername(dbUser.getUsername());
-        });
-        // mock deptService 的方法
-        DeptDO dept = randomPojo(DeptDO.class, o -> {
-            o.setId(importUser.getDeptId());
-            o.setStatus(CommonStatusEnum.ENABLE.getStatus());
-        });
-        when(deptService.getDept(eq(dept.getId()))).thenReturn(dept);
-
-        // 调用
-        UserImportRespVO respVO = userService.importUserList(newArrayList(importUser), true);
-        // 断言
-        assertEquals(0, respVO.getCreateUsernames().size());
-        assertEquals(1, respVO.getUpdateUsernames().size());
-        AdminUserDO user = userMapper.selectByUsername(respVO.getUpdateUsernames().get(0));
-        assertPojoEquals(importUser, user);
-        assertEquals(0, respVO.getFailureUsernames().size());
-    }
-
-    @Test
-    public void testValidateUserExists_notExists() {
-        assertServiceException(() -> userService.validateUserExists(randomLongId()), USER_NOT_EXISTS);
-    }
-
-    @Test
-    public void testValidateUsernameUnique_usernameExistsForCreate() {
-        // 准备参数
-        String username = randomString();
-        // mock 数据
-        userMapper.insert(randomAdminUserDO(o -> o.setUsername(username)));
-
-        // 调用,校验异常
-        assertServiceException(() -> userService.validateUsernameUnique(null, username),
-                USER_USERNAME_EXISTS);
-    }
-
-    @Test
-    public void testValidateUsernameUnique_usernameExistsForUpdate() {
-        // 准备参数
-        Long id = randomLongId();
-        String username = randomString();
-        // mock 数据
-        userMapper.insert(randomAdminUserDO(o -> o.setUsername(username)));
-
-        // 调用,校验异常
-        assertServiceException(() -> userService.validateUsernameUnique(id, username),
-                USER_USERNAME_EXISTS);
-    }
-
-    @Test
-    public void testValidateEmailUnique_emailExistsForCreate() {
-        // 准备参数
-        String email = randomString();
-        // mock 数据
-        userMapper.insert(randomAdminUserDO(o -> o.setEmail(email)));
-
-        // 调用,校验异常
-        assertServiceException(() -> userService.validateEmailUnique(null, email),
-                USER_EMAIL_EXISTS);
-    }
-
-    @Test
-    public void testValidateEmailUnique_emailExistsForUpdate() {
-        // 准备参数
-        Long id = randomLongId();
-        String email = randomString();
-        // mock 数据
-        userMapper.insert(randomAdminUserDO(o -> o.setEmail(email)));
-
-        // 调用,校验异常
-        assertServiceException(() -> userService.validateEmailUnique(id, email),
-                USER_EMAIL_EXISTS);
-    }
-
-    @Test
-    public void testValidateMobileUnique_mobileExistsForCreate() {
-        // 准备参数
-        String mobile = randomString();
-        // mock 数据
-        userMapper.insert(randomAdminUserDO(o -> o.setMobile(mobile)));
-
-        // 调用,校验异常
-        assertServiceException(() -> userService.validateMobileUnique(null, mobile),
-                USER_MOBILE_EXISTS);
-    }
-
-    @Test
-    public void testValidateMobileUnique_mobileExistsForUpdate() {
-        // 准备参数
-        Long id = randomLongId();
-        String mobile = randomString();
-        // mock 数据
-        userMapper.insert(randomAdminUserDO(o -> o.setMobile(mobile)));
-
-        // 调用,校验异常
-        assertServiceException(() -> userService.validateMobileUnique(id, mobile),
-                USER_MOBILE_EXISTS);
-    }
-
-    @Test
-    public void testValidateOldPassword_notExists() {
-        assertServiceException(() -> userService.validateOldPassword(randomLongId(), randomString()),
-                USER_NOT_EXISTS);
-    }
-
-    @Test
-    public void testValidateOldPassword_passwordFailed() {
-        // mock 数据
-        AdminUserDO user = randomAdminUserDO();
-        userMapper.insert(user);
-        // 准备参数
-        Long id = user.getId();
-        String oldPassword = user.getPassword();
-
-        // 调用,校验异常
-        assertServiceException(() -> userService.validateOldPassword(id, oldPassword),
-                USER_PASSWORD_FAILED);
-        // 校验调用
-        verify(passwordEncoder, times(1)).matches(eq(oldPassword), eq(user.getPassword()));
-    }
-
-    @Test
-    public void testUserListByPostIds() {
-        // 准备参数
-        Collection<Long> postIds = asSet(10L, 20L);
-        // mock user1 数据
-        AdminUserDO user1 = randomAdminUserDO(o -> o.setPostIds(asSet(10L, 30L)));
-        userMapper.insert(user1);
-        userPostMapper.insert(new UserPostDO().setUserId(user1.getId()).setPostId(10L));
-        userPostMapper.insert(new UserPostDO().setUserId(user1.getId()).setPostId(30L));
-        // mock user2 数据
-        AdminUserDO user2 = randomAdminUserDO(o -> o.setPostIds(singleton(100L)));
-        userMapper.insert(user2);
-        userPostMapper.insert(new UserPostDO().setUserId(user2.getId()).setPostId(100L));
-
-        // 调用
-        List<AdminUserDO> result = userService.getUserListByPostIds(postIds);
-        // 断言
-        assertEquals(1, result.size());
-        assertEquals(user1, result.get(0));
-    }
-
-    @Test
-    public void testGetUserList() {
-        // mock 数据
-        AdminUserDO user = randomAdminUserDO();
-        userMapper.insert(user);
-        // 测试 id 不匹配
-        userMapper.insert(randomAdminUserDO());
-        // 准备参数
-        Collection<Long> ids = singleton(user.getId());
-
-        // 调用
-        List<AdminUserDO> result = userService.getUserList(ids);
-        // 断言
-        assertEquals(1, result.size());
-        assertEquals(user, result.get(0));
-    }
-
-    @Test
-    public void testGetUserMap() {
-        // mock 数据
-        AdminUserDO user = randomAdminUserDO();
-        userMapper.insert(user);
-        // 测试 id 不匹配
-        userMapper.insert(randomAdminUserDO());
-        // 准备参数
-        Collection<Long> ids = singleton(user.getId());
-
-        // 调用
-        Map<Long, AdminUserDO> result = userService.getUserMap(ids);
-        // 断言
-        assertEquals(1, result.size());
-        assertEquals(user, result.get(user.getId()));
-    }
-
-    @Test
-    public void testGetUserListByNickname() {
-        // mock 数据
-        AdminUserDO user = randomAdminUserDO(o -> o.setNickname("芋头"));
-        userMapper.insert(user);
-        // 测试 nickname 不匹配
-        userMapper.insert(randomAdminUserDO(o -> o.setNickname("源码")));
-        // 准备参数
-        String nickname = "芋";
-
-        // 调用
-        List<AdminUserDO> result = userService.getUserListByNickname(nickname);
-        // 断言
-        assertEquals(1, result.size());
-        assertEquals(user, result.get(0));
-    }
-
-    @Test
-    public void testGetUserListByStatus() {
-        // mock 数据
-        AdminUserDO user = randomAdminUserDO(o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()));
-        userMapper.insert(user);
-        // 测试 status 不匹配
-        userMapper.insert(randomAdminUserDO(o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())));
-        // 准备参数
-        Integer status = CommonStatusEnum.DISABLE.getStatus();
-
-        // 调用
-        List<AdminUserDO> result = userService.getUserListByStatus(status);
-        // 断言
-        assertEquals(1, result.size());
-        assertEquals(user, result.get(0));
-    }
-
-    @Test
-    public void testValidateUserList_success() {
-        // mock 数据
-        AdminUserDO userDO = randomAdminUserDO().setStatus(CommonStatusEnum.ENABLE.getStatus());
-        userMapper.insert(userDO);
-        // 准备参数
-        List<Long> ids = singletonList(userDO.getId());
-
-        // 调用,无需断言
-        userService.validateUserList(ids);
-    }
-
-    @Test
-    public void testValidateUserList_notFound() {
-        // 准备参数
-        List<Long> ids = singletonList(randomLongId());
-
-        // 调用, 并断言异常
-        assertServiceException(() -> userService.validateUserList(ids), USER_NOT_EXISTS);
-    }
-
-    @Test
-    public void testValidateUserList_notEnable() {
-        // mock 数据
-        AdminUserDO userDO = randomAdminUserDO().setStatus(CommonStatusEnum.DISABLE.getStatus());
-        userMapper.insert(userDO);
-        // 准备参数
-        List<Long> ids = singletonList(userDO.getId());
-
-        // 调用, 并断言异常
-        assertServiceException(() -> userService.validateUserList(ids), USER_IS_DISABLE,
-                userDO.getNickname());
-    }
-
-    // ========== 随机对象 ==========
-
-    @SafeVarargs
-    private static AdminUserDO randomAdminUserDO(Consumer<AdminUserDO>... consumers) {
-        Consumer<AdminUserDO> consumer = (o) -> {
-            o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围
-            o.setSex(randomEle(SexEnum.values()).getSex()); // 保证 sex 的范围
-        };
-        return randomPojo(AdminUserDO.class, ArrayUtils.append(consumer, consumers));
-    }
-
-}

--
Gitblit v1.9.3