1.分页限制修改为最大 1000条

This commit is contained in:
2025-07-01 15:54:24 +08:00
parent 3498ba5030
commit ae65dbdd07
38 changed files with 2 additions and 9543 deletions

View File

@@ -1,337 +0,0 @@
package cn.iocoder.yudao.module.system.controller.admin.oauth2;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.map.MapUtil;
import cn.iocoder.yudao.framework.common.core.KeyValue;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.OAuth2OpenAccessTokenRespVO;
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.OAuth2OpenAuthorizeInfoRespVO;
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.OAuth2OpenCheckTokenRespVO;
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ApproveDO;
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ClientDO;
import cn.iocoder.yudao.module.system.enums.oauth2.OAuth2GrantTypeEnum;
import cn.iocoder.yudao.module.system.service.oauth2.OAuth2ApproveService;
import cn.iocoder.yudao.module.system.service.oauth2.OAuth2ClientService;
import cn.iocoder.yudao.module.system.service.oauth2.OAuth2GrantService;
import cn.iocoder.yudao.module.system.service.oauth2.OAuth2TokenService;
import org.assertj.core.util.Lists;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
import static java.util.Arrays.asList;
import static org.hamcrest.CoreMatchers.anyOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/**
* {@link OAuth2OpenController} 的单元测试
*
* @author 芋道源码
*/
public class OAuth2OpenControllerTest extends BaseMockitoUnitTest {
@InjectMocks
private OAuth2OpenController oauth2OpenController;
@Mock
private OAuth2GrantService oauth2GrantService;
@Mock
private OAuth2ClientService oauth2ClientService;
@Mock
private OAuth2ApproveService oauth2ApproveService;
@Mock
private OAuth2TokenService oauth2TokenService;
@Test
public void testPostAccessToken_authorizationCode() {
// 准备参数
String granType = OAuth2GrantTypeEnum.AUTHORIZATION_CODE.getGrantType();
String code = randomString();
String redirectUri = randomString();
String state = randomString();
HttpServletRequest request = mockRequest("test_client_id", "test_client_secret");
// mock 方法client
OAuth2ClientDO client = randomPojo(OAuth2ClientDO.class).setClientId("test_client_id");
when(oauth2ClientService.validOAuthClientFromCache(eq("test_client_id"), eq("test_client_secret"), eq(granType), eq(new ArrayList<>()), eq(redirectUri))).thenReturn(client);
// mock 方法(访问令牌)
OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class)
.setExpiresTime(LocalDateTimeUtil.offset(LocalDateTime.now(), 30000L, ChronoUnit.MILLIS));
when(oauth2GrantService.grantAuthorizationCodeForAccessToken(eq("test_client_id"),
eq(code), eq(redirectUri), eq(state))).thenReturn(accessTokenDO);
// 调用
CommonResult<OAuth2OpenAccessTokenRespVO> result = oauth2OpenController.postAccessToken(request, granType,
code, redirectUri, state, null, null, null, null);
// 断言
assertEquals(0, result.getCode());
assertPojoEquals(accessTokenDO, result.getData());
assertTrue(ObjectUtils.equalsAny(result.getData().getExpiresIn(), 29L, 30L)); // 执行过程会过去几毫秒
}
@Test
public void testPostAccessToken_password() {
// 准备参数
String granType = OAuth2GrantTypeEnum.PASSWORD.getGrantType();
String username = randomString();
String password = randomString();
String scope = "write read";
HttpServletRequest request = mockRequest("test_client_id", "test_client_secret");
// mock 方法client
OAuth2ClientDO client = randomPojo(OAuth2ClientDO.class).setClientId("test_client_id");
when(oauth2ClientService.validOAuthClientFromCache(eq("test_client_id"), eq("test_client_secret"),
eq(granType), eq(Lists.newArrayList("write", "read")), isNull())).thenReturn(client);
// mock 方法(访问令牌)
OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class)
.setExpiresTime(LocalDateTimeUtil.offset(LocalDateTime.now(), 30000L, ChronoUnit.MILLIS));
when(oauth2GrantService.grantPassword(eq(username), eq(password), eq("test_client_id"),
eq(Lists.newArrayList("write", "read")))).thenReturn(accessTokenDO);
// 调用
CommonResult<OAuth2OpenAccessTokenRespVO> result = oauth2OpenController.postAccessToken(request, granType,
null, null, null, username, password, scope, null);
// 断言
assertEquals(0, result.getCode());
assertPojoEquals(accessTokenDO, result.getData());
assertTrue(ObjectUtils.equalsAny(result.getData().getExpiresIn(), 29L, 30L)); // 执行过程会过去几毫秒
}
@Test
public void testPostAccessToken_refreshToken() {
// 准备参数
String granType = OAuth2GrantTypeEnum.REFRESH_TOKEN.getGrantType();
String refreshToken = randomString();
String password = randomString();
HttpServletRequest request = mockRequest("test_client_id", "test_client_secret");
// mock 方法client
OAuth2ClientDO client = randomPojo(OAuth2ClientDO.class).setClientId("test_client_id");
when(oauth2ClientService.validOAuthClientFromCache(eq("test_client_id"), eq("test_client_secret"),
eq(granType), eq(Lists.newArrayList()), isNull())).thenReturn(client);
// mock 方法(访问令牌)
OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class)
.setExpiresTime(LocalDateTimeUtil.offset(LocalDateTime.now(), 30000L, ChronoUnit.MILLIS));
when(oauth2GrantService.grantRefreshToken(eq(refreshToken), eq("test_client_id"))).thenReturn(accessTokenDO);
// 调用
CommonResult<OAuth2OpenAccessTokenRespVO> result = oauth2OpenController.postAccessToken(request, granType,
null, null, null, null, password, null, refreshToken);
// 断言
assertEquals(0, result.getCode());
assertPojoEquals(accessTokenDO, result.getData());
assertTrue(ObjectUtils.equalsAny(result.getData().getExpiresIn(), 29L, 30L)); // 执行过程会过去几毫秒
}
@Test
public void testPostAccessToken_implicit() {
// 调用,并断言
assertServiceException(() -> oauth2OpenController.postAccessToken(null,
OAuth2GrantTypeEnum.IMPLICIT.getGrantType(), null, null, null,
null, null, null, null),
new ErrorCode(400, "Token 接口不支持 implicit 授权模式"));
}
@Test
public void testRevokeToken() {
// 准备参数
HttpServletRequest request = mockRequest("demo_client_id", "demo_client_secret");
String token = randomString();
// mock 方法client
OAuth2ClientDO client = randomPojo(OAuth2ClientDO.class).setClientId("demo_client_id");
when(oauth2ClientService.validOAuthClientFromCache(eq("demo_client_id"),
eq("demo_client_secret"), isNull(), isNull(), isNull())).thenReturn(client);
// mock 方法(移除)
when(oauth2GrantService.revokeToken(eq("demo_client_id"), eq(token))).thenReturn(true);
// 调用
CommonResult<Boolean> result = oauth2OpenController.revokeToken(request, token);
// 断言
assertEquals(0, result.getCode());
assertTrue(result.getData());
}
@Test
public void testCheckToken() {
// 准备参数
HttpServletRequest request = mockRequest("demo_client_id", "demo_client_secret");
String token = randomString();
// mock 方法
OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class).setUserType(UserTypeEnum.ADMIN.getValue()).setExpiresTime(LocalDateTimeUtil.of(1653485731195L));
when(oauth2TokenService.checkAccessToken(eq(token))).thenReturn(accessTokenDO);
// 调用
CommonResult<OAuth2OpenCheckTokenRespVO> result = oauth2OpenController.checkToken(request, token);
// 断言
assertEquals(0, result.getCode());
assertPojoEquals(accessTokenDO, result.getData());
assertEquals(1653485731L, result.getData().getExp()); // 执行过程会过去几毫秒
}
@Test
public void testAuthorize() {
// 准备参数
String clientId = randomString();
// mock 方法client
OAuth2ClientDO client = randomPojo(OAuth2ClientDO.class).setClientId("demo_client_id").setScopes(ListUtil.toList("read", "write", "all"));
when(oauth2ClientService.validOAuthClientFromCache(eq(clientId))).thenReturn(client);
// mock 方法approve
List<OAuth2ApproveDO> approves = asList(
randomPojo(OAuth2ApproveDO.class).setScope("read").setApproved(true),
randomPojo(OAuth2ApproveDO.class).setScope("write").setApproved(false));
when(oauth2ApproveService.getApproveList(isNull(), eq(UserTypeEnum.ADMIN.getValue()), eq(clientId))).thenReturn(approves);
// 调用
CommonResult<OAuth2OpenAuthorizeInfoRespVO> result = oauth2OpenController.authorize(clientId);
// 断言
assertEquals(0, result.getCode());
assertPojoEquals(client, result.getData().getClient());
assertEquals(new KeyValue<>("read", true), result.getData().getScopes().get(0));
assertEquals(new KeyValue<>("write", false), result.getData().getScopes().get(1));
assertEquals(new KeyValue<>("all", false), result.getData().getScopes().get(2));
}
@Test
public void testApproveOrDeny_grantTypeError() {
// 调用,并断言
assertServiceException(() -> oauth2OpenController.approveOrDeny(randomString(), null,
null, null, null, null),
new ErrorCode(400, "response_type 参数值只允许 code 和 token"));
}
@Test // autoApprove = true但是不通过
public void testApproveOrDeny_autoApproveNo() {
// 准备参数
String responseType = "code";
String clientId = randomString();
String scope = "{\"read\": true, \"write\": false}";
String redirectUri = randomString();
String state = randomString();
// mock 方法
OAuth2ClientDO client = randomPojo(OAuth2ClientDO.class);
when(oauth2ClientService.validOAuthClientFromCache(eq(clientId), isNull(), eq("authorization_code"),
eq(asSet("read", "write")), eq(redirectUri))).thenReturn(client);
// 调用
CommonResult<String> result = oauth2OpenController.approveOrDeny(responseType, clientId,
scope, redirectUri, true, state);
// 断言
assertEquals(0, result.getCode());
assertNull(result.getData());
}
@Test // autoApprove = false但是不通过
public void testApproveOrDeny_ApproveNo() {
// 准备参数
String responseType = "token";
String clientId = randomString();
String scope = "{\"read\": true, \"write\": false}";
String redirectUri = "https://www.iocoder.cn";
String state = "test";
// mock 方法
OAuth2ClientDO client = randomPojo(OAuth2ClientDO.class);
when(oauth2ClientService.validOAuthClientFromCache(eq(clientId), isNull(), eq("implicit"),
eq(asSet("read", "write")), eq(redirectUri))).thenReturn(client);
// 调用
CommonResult<String> result = oauth2OpenController.approveOrDeny(responseType, clientId,
scope, redirectUri, false, state);
// 断言
assertEquals(0, result.getCode());
assertEquals("https://www.iocoder.cn#error=access_denied&error_description=User%20denied%20access&state=test", result.getData());
}
@Test // autoApprove = true通过 + token
public void testApproveOrDeny_autoApproveWithToken() {
// 准备参数
String responseType = "token";
String clientId = randomString();
String scope = "{\"read\": true, \"write\": false}";
String redirectUri = "https://www.iocoder.cn";
String state = "test";
// mock 方法client)
OAuth2ClientDO client = randomPojo(OAuth2ClientDO.class).setClientId(clientId).setAdditionalInformation(null);
when(oauth2ClientService.validOAuthClientFromCache(eq(clientId), isNull(), eq("implicit"),
eq(asSet("read", "write")), eq(redirectUri))).thenReturn(client);
// mock 方法(场景一)
when(oauth2ApproveService.checkForPreApproval(isNull(), eq(UserTypeEnum.ADMIN.getValue()),
eq(clientId), eq(SetUtils.asSet("read", "write")))).thenReturn(true);
// mock 方法(访问令牌)
OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class)
.setAccessToken("test_access_token").setExpiresTime(LocalDateTimeUtil.offset(LocalDateTime.now(), 30010L, ChronoUnit.MILLIS));
when(oauth2GrantService.grantImplicit(isNull(), eq(UserTypeEnum.ADMIN.getValue()),
eq(clientId), eq(ListUtil.toList("read")))).thenReturn(accessTokenDO);
// 调用
CommonResult<String> result = oauth2OpenController.approveOrDeny(responseType, clientId,
scope, redirectUri, true, state);
// 断言
assertEquals(0, result.getCode());
assertThat(result.getData(), anyOf( // 29 和 30 都有一定概率,主要是时间计算
is("https://www.iocoder.cn#access_token=test_access_token&token_type=bearer&state=test&expires_in=29&scope=read"),
is("https://www.iocoder.cn#access_token=test_access_token&token_type=bearer&state=test&expires_in=30&scope=read")
));
}
@Test // autoApprove = false通过 + code
public void testApproveOrDeny_approveWithCode() {
// 准备参数
String responseType = "code";
String clientId = randomString();
String scope = "{\"read\": true, \"write\": false}";
String redirectUri = "https://www.iocoder.cn";
String state = "test";
// mock 方法client)
OAuth2ClientDO client = randomPojo(OAuth2ClientDO.class).setClientId(clientId).setAdditionalInformation(null);
when(oauth2ClientService.validOAuthClientFromCache(eq(clientId), isNull(), eq("authorization_code"),
eq(asSet("read", "write")), eq(redirectUri))).thenReturn(client);
// mock 方法(场景二)
when(oauth2ApproveService.updateAfterApproval(isNull(), eq(UserTypeEnum.ADMIN.getValue()), eq(clientId),
eq(MapUtil.builder(new LinkedHashMap<String, Boolean>()).put("read", true).put("write", false).build())))
.thenReturn(true);
// mock 方法(访问令牌)
String authorizationCode = "test_code";
when(oauth2GrantService.grantAuthorizationCodeForCode(isNull(), eq(UserTypeEnum.ADMIN.getValue()),
eq(clientId), eq(ListUtil.toList("read")), eq(redirectUri), eq(state))).thenReturn(authorizationCode);
// 调用
CommonResult<String> result = oauth2OpenController.approveOrDeny(responseType, clientId,
scope, redirectUri, false, state);
// 断言
assertEquals(0, result.getCode());
assertEquals("https://www.iocoder.cn?code=test_code&state=test", result.getData());
}
private HttpServletRequest mockRequest(String clientId, String secret) {
HttpServletRequest request = mock(HttpServletRequest.class);
when(request.getParameter(eq("client_id"))).thenReturn(clientId);
when(request.getParameter(eq("client_secret"))).thenReturn(secret);
return request;
}
}

View File

@@ -1,160 +0,0 @@
package cn.iocoder.yudao.module.system.framework.sms.core.client.impl;
import cn.iocoder.yudao.framework.common.core.KeyValue;
import cn.iocoder.yudao.framework.common.util.http.HttpUtils;
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO;
import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsSendRespDTO;
import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO;
import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
import cn.iocoder.yudao.module.system.framework.sms.core.property.SmsChannelProperties;
import com.google.common.collect.Lists;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.MockedStatic;
import org.mockito.stubbing.Answer;
import java.time.LocalDateTime;
import java.util.List;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.anyMap;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mockStatic;
/**
* {@link cn.iocoder.yudao.module.system.framework.sms.core.client.impl.AliyunSmsClient} 的单元测试
*
* @author 芋道源码
*/
public class AliyunSmsClientTest extends BaseMockitoUnitTest {
private final SmsChannelProperties properties = new SmsChannelProperties()
.setApiKey(randomString()) // 随机一个 apiKey避免构建报错
.setApiSecret(randomString()) // 随机一个 apiSecret避免构建报错
.setSignature("芋道源码");
@InjectMocks
private final AliyunSmsClient smsClient = new AliyunSmsClient(properties);
@Test
public void tesSendSms_success() throws Throwable {
try (MockedStatic<HttpUtils> httpUtilsMockedStatic = mockStatic(HttpUtils.class)) {
// 准备参数
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 方法
httpUtilsMockedStatic.when(() -> HttpUtils.post(anyString(), anyMap(), anyString()))
.thenReturn("{\"Message\":\"OK\",\"RequestId\":\"30067CE9-3710-5984-8881-909B21D8DB28\",\"Code\":\"OK\",\"BizId\":\"800025323183427988\"}");
httpUtilsMockedStatic.when(() -> HttpUtils.encodeUtf8(anyString()))
.then((Answer<String>) invocationOnMock -> (String) invocationOnMock.getArguments()[0]);
// 调用
SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile,
apiTemplateId, templateParams);
// 断言
assertTrue(result.getSuccess());
assertEquals("30067CE9-3710-5984-8881-909B21D8DB28", result.getApiRequestId());
assertEquals("OK", result.getApiCode());
assertEquals("OK", result.getApiMsg());
assertEquals("800025323183427988", result.getSerialNo());
}
}
@Test
public void tesSendSms_fail() throws Throwable {
try (MockedStatic<HttpUtils> httpUtilsMockedStatic = mockStatic(HttpUtils.class)) {
// 准备参数
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 方法
httpUtilsMockedStatic.when(() -> HttpUtils.post(anyString(), anyMap(), anyString()))
.thenReturn("{\"Message\":\"手机号码格式错误\",\"RequestId\":\"B7700B8E-227E-5886-9564-26036172F01F\",\"Code\":\"isv.MOBILE_NUMBER_ILLEGAL\"}");
httpUtilsMockedStatic.when(() -> HttpUtils.encodeUtf8(anyString()))
.then((Answer<String>) invocationOnMock -> (String) invocationOnMock.getArguments()[0]);
// 调用
SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile, apiTemplateId, templateParams);
// 断言
assertFalse(result.getSuccess());
assertEquals("B7700B8E-227E-5886-9564-26036172F01F", result.getApiRequestId());
assertEquals("isv.MOBILE_NUMBER_ILLEGAL", result.getApiCode());
assertEquals("手机号码格式错误", result.getApiMsg());
assertNull(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 {
try (MockedStatic<HttpUtils> httpUtilsMockedStatic = mockStatic(HttpUtils.class)) {
// 准备参数
String apiTemplateId = randomString();
// mock 方法
httpUtilsMockedStatic.when(() -> HttpUtils.post(anyString(), anyMap(), anyString()))
.thenReturn("{\"TemplateCode\":\"SMS_207945135\",\"RequestId\":\"6F4CC077-29C8-5BA5-AB62-5FF95068A5AC\",\"Message\":\"OK\",\"TemplateContent\":\"您的验证码${code}该验证码5分钟内有效请勿泄漏于他人\",\"TemplateName\":\"公告通知\",\"TemplateType\":0,\"Code\":\"OK\",\"CreateDate\":\"2020-12-23 17:34:42\",\"Reason\":\"无审批备注\",\"TemplateStatus\":1}");
httpUtilsMockedStatic.when(() -> HttpUtils.encodeUtf8(anyString()))
.then((Answer<String>) invocationOnMock -> (String) invocationOnMock.getArguments()[0]);
// 调用
SmsTemplateRespDTO result = smsClient.getSmsTemplate(apiTemplateId);
// 断言
assertEquals("SMS_207945135", result.getId());
assertEquals("您的验证码${code}该验证码5分钟内有效请勿泄漏于他人", result.getContent());
assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), result.getAuditStatus());
assertEquals("无审批备注", 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)");
}
}

View File

@@ -1,127 +0,0 @@
package cn.iocoder.yudao.module.system.framework.sms.core.client.impl;
import cn.iocoder.yudao.framework.common.core.KeyValue;
import cn.iocoder.yudao.framework.common.util.http.HttpUtils;
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO;
import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsSendRespDTO;
import cn.iocoder.yudao.module.system.framework.sms.core.property.SmsChannelProperties;
import com.google.common.collect.Lists;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.MockedStatic;
import java.time.LocalDateTime;
import java.util.List;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mockStatic;
/**
* {@link HuaweiSmsClient} 的单元测试
*
* @author scholar
*/
public class HuaweiSmsClientTest extends BaseMockitoUnitTest {
private final SmsChannelProperties properties = new SmsChannelProperties()
.setApiKey(randomString() + " " + randomString()) // 随机一个 apiKey避免构建报错
.setApiSecret(randomString()) // 随机一个 apiSecret避免构建报错
.setSignature("芋道源码");
@InjectMocks
private HuaweiSmsClient smsClient = new HuaweiSmsClient(properties);
@Test
public void testDoSendSms_success() throws Throwable {
try (MockedStatic<HttpUtils> httpUtilsMockedStatic = mockStatic(HttpUtils.class)) {
// 准备参数
Long sendLogId = randomLongId();
String mobile = randomString();
String apiTemplateId = randomString() + " " + randomString();
List<KeyValue<String, Object>> templateParams = Lists.newArrayList(
new KeyValue<>("1", 1234), new KeyValue<>("2", "login"));
// mock 方法
httpUtilsMockedStatic.when(() -> HttpUtils.post(anyString(), anyMap(), anyString()))
.thenReturn("{\"result\":[{\"originTo\":\"+86155****5678\",\"createTime\":\"2018-05-25T16:34:34Z\",\"from\":\"1069********0012\",\"smsMsgId\":\"d6e3cdd0-522b-4692-8304-a07553cdf591_8539659\",\"status\":\"000000\",\"countryId\":\"CN\",\"total\":2}],\"code\":\"000000\",\"description\":\"Success\"}\n");
// 调用
SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile,
apiTemplateId, templateParams);
// 断言
assertTrue(result.getSuccess());
assertEquals("d6e3cdd0-522b-4692-8304-a07553cdf591_8539659", result.getSerialNo());
assertEquals("000000", result.getApiCode());
}
}
@Test
public void testDoSendSms_fail_01() throws Throwable {
try (MockedStatic<HttpUtils> httpUtilsMockedStatic = mockStatic(HttpUtils.class)) {
// 准备参数
Long sendLogId = randomLongId();
String mobile = randomString();
String apiTemplateId = randomString() + " " + randomString();
List<KeyValue<String, Object>> templateParams = Lists.newArrayList(
new KeyValue<>("1", 1234), new KeyValue<>("2", "login"));
// mock 方法
httpUtilsMockedStatic.when(() -> HttpUtils.post(anyString(), anyMap(), anyString()))
.thenReturn("{\"result\":[{\"total\":1,\"originTo\":\"17321315478\",\"createTime\":\"2024-08-18T11:32:20Z\",\"from\":\"x8824060312575\",\"smsMsgId\":\"06e4b966-ad87-479f-8b74-f57fb7aafb60_304613461\",\"countryId\":\"CN\",\"status\":\"E200033\"}],\"code\":\"E000510\",\"description\":\"The SMS fails to be sent. For details, see status.\"}");
// 调用
SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile,
apiTemplateId, templateParams);
// 断言
assertFalse(result.getSuccess());
assertEquals("06e4b966-ad87-479f-8b74-f57fb7aafb60_304613461", result.getSerialNo());
assertEquals("E200033", result.getApiCode());
}
}
@Test
public void testDoSendSms_fail_02() throws Throwable {
try (MockedStatic<HttpUtils> httpUtilsMockedStatic = mockStatic(HttpUtils.class)) {
// 准备参数
Long sendLogId = randomLongId();
String mobile = randomString();
String apiTemplateId = randomString() + " " + randomString();
List<KeyValue<String, Object>> templateParams = Lists.newArrayList(
new KeyValue<>("1", 1234), new KeyValue<>("2", "login"));
// mock 方法
httpUtilsMockedStatic.when(() -> HttpUtils.post(anyString(), anyMap(), anyString()))
.thenReturn("{\"code\":\"E000102\",\"description\":\"Invalid app_key.\"}");
// 调用
SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile,
apiTemplateId, templateParams);
// 断言
assertFalse(result.getSuccess());
assertEquals("E000102", result.getApiCode());
assertEquals("Invalid app_key.", result.getApiMsg());
}
}
@Test
public void testParseSmsReceiveStatus() {
// 准备参数
String text = "sequence=1&total=1&statusDesc=%E7%94%A8%E6%88%B7%E5%B7%B2%E6%88%90%E5%8A%9F%E6%94%B6%E5%88%B0%E7%9F%AD%E4%BF%A1&updateTime=2024-08-15T03%3A00%3A34Z&source=2&smsMsgId=70207ed7-1d02-41b0-8537-bb25fd1c2364_143684459&status=DELIVRD&extend=176";
// 调用
List<SmsReceiveRespDTO> statuses = smsClient.parseSmsReceiveStatus(text);
// 断言
assertEquals(1, statuses.size());
SmsReceiveRespDTO status = statuses.get(0);
assertTrue(status.getSuccess());
assertEquals("DELIVRD", status.getErrorCode());
assertEquals(LocalDateTime.of(2024, 8, 15, 3, 0, 34), status.getReceiveTime());
assertEquals("70207ed7-1d02-41b0-8537-bb25fd1c2364_143684459", status.getSerialNo());
}
}

View File

@@ -1,131 +0,0 @@
package cn.iocoder.yudao.module.system.framework.sms.core.client.impl;
import cn.iocoder.yudao.framework.common.core.KeyValue;
import cn.iocoder.yudao.framework.common.util.http.HttpUtils;
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO;
import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsSendRespDTO;
import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO;
import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
import cn.iocoder.yudao.module.system.framework.sms.core.property.SmsChannelProperties;
import com.google.common.collect.Lists;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.MockedStatic;
import java.time.LocalDateTime;
import java.util.List;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mockStatic;
/**
* {@link QiniuSmsClient} 的单元测试
*
* @author scholar
*/
public class QiniuSmsClientTest extends BaseMockitoUnitTest {
private final SmsChannelProperties properties = new SmsChannelProperties()
.setApiKey(randomString())// 随机一个 apiKey避免构建报错
.setApiSecret(randomString()) // 随机一个 apiSecret避免构建报错
.setSignature("芋道源码");
@InjectMocks
private QiniuSmsClient smsClient = new QiniuSmsClient(properties);
@Test
public void testDoSendSms_success() throws Throwable {
try (MockedStatic<HttpUtils> httpUtilsMockedStatic = mockStatic(HttpUtils.class)) {
// 准备参数
Long sendLogId = randomLongId();
String mobile = randomString();
String apiTemplateId = randomString() + " " + randomString();
List<KeyValue<String, Object>> templateParams = Lists.newArrayList(
new KeyValue<>("1", 1234), new KeyValue<>("2", "login"));
// mock 方法
httpUtilsMockedStatic.when(() -> HttpUtils.post(anyString(), anyMap(), anyString()))
.thenReturn("{\"message_id\":\"17245678901\"}");
// 调用
SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile,
apiTemplateId, templateParams);
// 断言
assertTrue(result.getSuccess());
assertEquals("17245678901", result.getSerialNo());
}
}
@Test
public void testDoSendSms_fail() throws Throwable {
try (MockedStatic<HttpUtils> httpUtilsMockedStatic = mockStatic(HttpUtils.class)) {
// 准备参数
Long sendLogId = randomLongId();
String mobile = randomString();
String apiTemplateId = randomString() + " " + randomString();
List<KeyValue<String, Object>> templateParams = Lists.newArrayList(
new KeyValue<>("1", 1234), new KeyValue<>("2", "login"));
// mock 方法
httpUtilsMockedStatic.when(() -> HttpUtils.post(anyString(), anyMap(), anyString()))
.thenReturn("{\"error\":\"BadToken\",\"message\":\"Your authorization token is invalid\",\"request_id\":\"etziWcJFo1C8Ne8X\"}");
// 调用
SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile,
apiTemplateId, templateParams);
// 断言
assertFalse(result.getSuccess());
assertEquals("BadToken", result.getApiCode());
assertEquals("Your authorization token is invalid", result.getApiMsg());
assertEquals("etziWcJFo1C8Ne8X", result.getApiRequestId());
}
}
@Test
public void testGetSmsTemplate() throws Throwable {
try (MockedStatic<HttpUtils> httpUtilsMockedStatic = mockStatic(HttpUtils.class)) {
// 准备参数
String apiTemplateId = randomString();
// mock 方法
httpUtilsMockedStatic.when(() -> HttpUtils.get(anyString(), anyMap()))
.thenReturn("{\"audit_status\":\"passed\",\"created_at\":1724231187,\"description\":\"\",\"disable_broadcast\":false,\"disable_broadcast_reason\":\"\",\"disable_reason\":\"\",\"disabled\":false,\"id\":\"1826184073773596672\",\"is_oversea\":false,\"name\":\"dd\",\"parameters\":[\"code\"],\"reject_reason\":\"\",\"signature_id\":\"1826099896017498112\",\"signature_text\":\"yudao\",\"template\":\"您的验证码为:${code}\",\"type\":\"verification\",\"uid\":1383022432,\"updated_at\":1724288561,\"variable_count\":0}");
// 调用
SmsTemplateRespDTO result = smsClient.getSmsTemplate(apiTemplateId);
// 断言
assertEquals("1826184073773596672", result.getId());
assertEquals("您的验证码为:${code}", result.getContent());
assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), result.getAuditStatus());
assertEquals("", result.getAuditReason());
}
}
@Test
public void testParseSmsReceiveStatus() {
// 准备参数
String text = "{\"items\":[{\"mobile\":\"18881234567\",\"message_id\":\"10135515063508004167\",\"status\":\"DELIVRD\",\"delivrd_at\":1724591666,\"error\":\"DELIVRD\",\"seq\":\"123\"}]}";
// 调用
List<SmsReceiveRespDTO> statuses = smsClient.parseSmsReceiveStatus(text);
// 断言
assertEquals(1, statuses.size());
SmsReceiveRespDTO status = statuses.get(0);
assertTrue(status.getSuccess());
assertEquals("DELIVRD", status.getErrorMsg());
assertEquals(LocalDateTime.of(2024, 8, 25, 21, 14, 26), status.getReceiveTime());
assertEquals("18881234567", status.getMobile());
assertEquals("10135515063508004167", status.getSerialNo());
assertEquals(123, status.getLogId());
}
@Test
public void testConvertSmsTemplateAuditStatus() {
assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(),
smsClient.convertSmsTemplateAuditStatus("passed"));
assertEquals(SmsTemplateAuditStatusEnum.CHECKING.getStatus(),
smsClient.convertSmsTemplateAuditStatus("reviewing"));
assertEquals(SmsTemplateAuditStatusEnum.FAIL.getStatus(),
smsClient.convertSmsTemplateAuditStatus("rejected"));
assertThrows(IllegalArgumentException.class, () -> smsClient.convertSmsTemplateAuditStatus("unknown"),
"未知审核状态(3)");
}
}

View File

@@ -1,151 +0,0 @@
package cn.iocoder.yudao.module.system.framework.sms.core.client.impl;
import cn.hutool.core.collection.ListUtil;
import cn.iocoder.yudao.framework.common.core.KeyValue;
import cn.iocoder.yudao.module.system.framework.sms.core.client.SmsClient;
import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsSendRespDTO;
import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO;
import cn.iocoder.yudao.module.system.framework.sms.core.property.SmsChannelProperties;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import java.util.List;
/**
* 各种 {@link SmsClient} 的集成测试
*
* @author 芋道源码
*/
public class SmsClientTests {
// ========== 阿里云 ==========
@Test
@Disabled
public void testAliyunSmsClient_getSmsTemplate() throws Throwable {
SmsChannelProperties properties = new SmsChannelProperties()
.setApiKey(System.getenv("SMS_ALIYUN_ACCESS_KEY"))
.setApiSecret(System.getenv("SMS_ALIYUN_SECRET_KEY"));
AliyunSmsClient client = new AliyunSmsClient(properties);
// 准备参数
String apiTemplateId = "SMS_207945135";
// 调用
SmsTemplateRespDTO template = client.getSmsTemplate(apiTemplateId);
// 打印结果
System.out.println(template);
}
@Test
@Disabled
public void testAliyunSmsClient_sendSms() throws Throwable {
SmsChannelProperties properties = new SmsChannelProperties()
.setApiKey(System.getenv("SMS_ALIYUN_ACCESS_KEY"))
.setApiSecret(System.getenv("SMS_ALIYUN_SECRET_KEY"))
.setSignature("Ballcat");
AliyunSmsClient client = new AliyunSmsClient(properties);
// 准备参数
Long sendLogId = System.currentTimeMillis();
String mobile = "15601691323";
String apiTemplateId = "SMS_207945135";
// 调用
SmsSendRespDTO sendRespDTO = client.sendSms(sendLogId, mobile, apiTemplateId, ListUtil.of(new KeyValue<>("code", "1024")));
// 打印结果
System.out.println(sendRespDTO);
}
// ========== 腾讯云 ==========
@Test
@Disabled
public void testTencentSmsClient_sendSms() throws Throwable {
String sdkAppId = "1400500458";
SmsChannelProperties properties = new SmsChannelProperties()
.setApiKey(System.getenv("SMS_TENCENT_ACCESS_KEY") + " " + sdkAppId)
.setApiSecret(System.getenv("SMS_TENCENT_SECRET_KEY"))
.setSignature("芋道源码");
TencentSmsClient client = new TencentSmsClient(properties);
// 准备参数
Long sendLogId = System.currentTimeMillis();
String mobile = "15601691323";
String apiTemplateId = "358212";
// 调用
SmsSendRespDTO sendRespDTO = client.sendSms(sendLogId, mobile, apiTemplateId, ListUtil.of(new KeyValue<>("code", "1024")));
// 打印结果
System.out.println(sendRespDTO);
}
@Test
@Disabled
public void testTencentSmsClient_getSmsTemplate() throws Throwable {
String sdkAppId = "1400500458";
SmsChannelProperties properties = new SmsChannelProperties()
.setApiKey(System.getenv("SMS_TENCENT_ACCESS_KEY") + " " + sdkAppId)
.setApiSecret(System.getenv("SMS_TENCENT_SECRET_KEY"))
.setSignature("芋道源码");
TencentSmsClient client = new TencentSmsClient(properties);
// 准备参数
String apiTemplateId = "358212";
// 调用
SmsTemplateRespDTO template = client.getSmsTemplate(apiTemplateId);
// 打印结果
System.out.println(template);
}
// ========== 华为云 ==========
@Test
@Disabled
public void testHuaweiSmsClient_sendSms() throws Throwable {
String sender = "x8824060312575";
SmsChannelProperties properties = new SmsChannelProperties()
.setApiKey(System.getenv("SMS_HUAWEI_ACCESS_KEY") + " " + sender)
.setApiSecret(System.getenv("SMS_HUAWEI_SECRET_KEY"))
.setSignature("runpu");
HuaweiSmsClient client = new HuaweiSmsClient(properties);
// 准备参数
Long sendLogId = System.currentTimeMillis();
String mobile = "17321315478";
String apiTemplateId = "3644cdab863546a3b718d488659a99ef";
List<KeyValue<String, Object>> templateParams = ListUtil.of(new KeyValue<>("code", "1024"));
// 调用
SmsSendRespDTO smsSendRespDTO = client.sendSms(sendLogId, mobile, apiTemplateId, templateParams);
// 打印结果
System.out.println(smsSendRespDTO);
}
// ========== 七牛云 ==========
@Test
@Disabled
public void testQiniuSmsClient_sendSms() throws Throwable {
SmsChannelProperties properties = new SmsChannelProperties()
.setApiKey("SMS_QINIU_ACCESS_KEY")
.setApiSecret("SMS_QINIU_SECRET_KEY");
QiniuSmsClient client = new QiniuSmsClient(properties);
// 准备参数
Long sendLogId = System.currentTimeMillis();
String mobile = "17321315478";
String apiTemplateId = "3644cdab863546a3b718d488659a99ef";
List<KeyValue<String, Object>> templateParams = ListUtil.of(new KeyValue<>("code", "1122"));
// 调用
SmsSendRespDTO smsSendRespDTO = client.sendSms(sendLogId, mobile, apiTemplateId, templateParams);
// 打印结果
System.out.println(smsSendRespDTO);
}
@Test
@Disabled
public void testQiniuSmsClient_getSmsTemplate() throws Throwable {
SmsChannelProperties properties = new SmsChannelProperties()
.setApiKey("SMS_QINIU_ACCESS_KEY")
.setApiSecret("SMS_QINIU_SECRET_KEY");
QiniuSmsClient client = new QiniuSmsClient(properties);
// 准备参数
String apiTemplateId = "3644cdab863546a3b718d488659a99ef";
// 调用
SmsTemplateRespDTO template = client.getSmsTemplate(apiTemplateId);
// 打印结果
System.out.println(template);
}
}

View File

@@ -1,218 +0,0 @@
package cn.iocoder.yudao.module.system.framework.sms.core.client.impl;
import cn.iocoder.yudao.framework.common.core.KeyValue;
import cn.iocoder.yudao.framework.common.util.http.HttpUtils;
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO;
import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsSendRespDTO;
import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO;
import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
import cn.iocoder.yudao.module.system.framework.sms.core.property.SmsChannelProperties;
import com.google.common.collect.Lists;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.MockedStatic;
import java.time.LocalDateTime;
import java.util.List;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mockStatic;
/**
* {@link TencentSmsClient} 的单元测试
*
* @author shiwp
*/
public class TencentSmsClientTest extends BaseMockitoUnitTest {
private final SmsChannelProperties properties = new SmsChannelProperties()
.setApiKey(randomString() + " " + randomString()) // 随机一个 apiKey避免构建报错
.setApiSecret(randomString()) // 随机一个 apiSecret避免构建报错
.setSignature("芋道源码");
@InjectMocks
private TencentSmsClient smsClient = new TencentSmsClient(properties);
@Test
public void testDoSendSms_success() throws Throwable {
try (MockedStatic<HttpUtils> httpUtilsMockedStatic = mockStatic(HttpUtils.class)) {
// 准备参数
Long sendLogId = randomLongId();
String mobile = randomString();
String apiTemplateId = randomString();
List<KeyValue<String, Object>> templateParams = Lists.newArrayList(
new KeyValue<>("1", 1234), new KeyValue<>("2", "login"));
// mock 方法
httpUtilsMockedStatic.when(() -> HttpUtils.post(anyString(), anyMap(), anyString()))
.thenReturn("{\n" +
" \"Response\": {\n" +
" \"SendStatusSet\": [\n" +
" {\n" +
" \"SerialNo\": \"5000:1045710669157053657849499619\",\n" +
" \"PhoneNumber\": \"+8618511122233\",\n" +
" \"Fee\": 1,\n" +
" \"SessionContext\": \"test\",\n" +
" \"Code\": \"Ok\",\n" +
" \"Message\": \"send success\",\n" +
" \"IsoCode\": \"CN\"\n" +
" },\n" +
" ],\n" +
" \"RequestId\": \"a0aabda6-cf91-4f3e-a81f-9198114a2279\"\n" +
" }\n" +
"}");
// 调用
SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile,
apiTemplateId, templateParams);
// 断言
assertTrue(result.getSuccess());
assertEquals("5000:1045710669157053657849499619", result.getSerialNo());
assertEquals("a0aabda6-cf91-4f3e-a81f-9198114a2279", result.getApiRequestId());
assertEquals("send success", result.getApiMsg());
}
}
@Test
public void testDoSendSms_fail_01() throws Throwable {
try (MockedStatic<HttpUtils> httpUtilsMockedStatic = mockStatic(HttpUtils.class)) {
// 准备参数
Long sendLogId = randomLongId();
String mobile = randomString();
String apiTemplateId = randomString();
List<KeyValue<String, Object>> templateParams = Lists.newArrayList(
new KeyValue<>("1", 1234), new KeyValue<>("2", "login"));
// mock 方法
httpUtilsMockedStatic.when(() -> HttpUtils.post(anyString(), anyMap(), anyString()))
.thenReturn("{\n" +
" \"Response\": {\n" +
" \"SendStatusSet\": [\n" +
" {\n" +
" \"SerialNo\": \"5000:1045710669157053657849499619\",\n" +
" \"PhoneNumber\": \"+8618511122233\",\n" +
" \"Fee\": 1,\n" +
" \"SessionContext\": \"test\",\n" +
" \"Code\": \"ERROR\",\n" +
" \"Message\": \"send success\",\n" +
" \"IsoCode\": \"CN\"\n" +
" },\n" +
" ],\n" +
" \"RequestId\": \"a0aabda6-cf91-4f3e-a81f-9198114a2279\"\n" +
" }\n" +
"}");
// 调用
SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile,
apiTemplateId, templateParams);
// 断言
assertFalse(result.getSuccess());
assertEquals("5000:1045710669157053657849499619", result.getSerialNo());
assertEquals("a0aabda6-cf91-4f3e-a81f-9198114a2279", result.getApiRequestId());
assertEquals("send success", result.getApiMsg());
}
}
@Test
public void testDoSendSms_fail_02() throws Throwable {
try (MockedStatic<HttpUtils> httpUtilsMockedStatic = mockStatic(HttpUtils.class)) {
// 准备参数
Long sendLogId = randomLongId();
String mobile = randomString();
String apiTemplateId = randomString();
List<KeyValue<String, Object>> templateParams = Lists.newArrayList(
new KeyValue<>("1", 1234), new KeyValue<>("2", "login"));
// mock 方法
httpUtilsMockedStatic.when(() -> HttpUtils.post(anyString(), anyMap(), anyString()))
.thenReturn("{\"Response\":{\"Error\":{\"Code\":\"AuthFailure.SecretIdNotFound\",\"Message\":\"The SecretId is not found, please ensure that your SecretId is correct.\"},\"RequestId\":\"2a88f82a-261c-4ac6-9fa9-c7d01aaa486a\"}}");
// 调用
SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile,
apiTemplateId, templateParams);
// 断言
assertFalse(result.getSuccess());
assertEquals("2a88f82a-261c-4ac6-9fa9-c7d01aaa486a", result.getApiRequestId());
assertEquals("AuthFailure.SecretIdNotFound", result.getApiCode());
assertEquals("The SecretId is not found, please ensure that your SecretId is correct.", result.getApiMsg());
}
}
@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" +
"]";
// 调用
List<SmsReceiveRespDTO> statuses = smsClient.parseSmsReceiveStatus(text);
// 断言
assertEquals(1, statuses.size());
assertTrue(statuses.get(0).getSuccess());
assertEquals("DELIVRD", statuses.get(0).getErrorCode());
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());
}
@Test
public void testGetSmsTemplate() throws Throwable {
try (MockedStatic<HttpUtils> httpUtilsMockedStatic = mockStatic(HttpUtils.class)) {
// 准备参数
String apiTemplateId = "1122";
// mock 方法
httpUtilsMockedStatic.when(() -> HttpUtils.post(anyString(), anyMap(), anyString()))
.thenReturn("{ \"Response\": {\n" +
" \"DescribeTemplateStatusSet\": [\n" +
" {\n" +
" \"TemplateName\": \"验证码\",\n" +
" \"TemplateId\": 1122,\n" +
" \"International\": 0,\n" +
" \"ReviewReply\": \"审批备注\",\n" +
" \"CreateTime\": 1617379200,\n" +
" \"TemplateContent\": \"您的验证码是{1}\",\n" +
" \"StatusCode\": 0\n" +
" },\n" +
" \n" +
" ],\n" +
" \"RequestId\": \"f36e4f00-605e-49b1-ad0d-bfaba81c7325\"\n" +
" }}");
// 调用
SmsTemplateRespDTO result = smsClient.getSmsTemplate(apiTemplateId);
// 断言
assertEquals("1122", result.getId());
assertEquals("您的验证码是{1}", result.getContent());
assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), result.getAuditStatus());
assertEquals("审批备注", 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)");
}
}

View File

@@ -1,356 +0,0 @@
package cn.iocoder.yudao.module.system.service.auth;
import cn.hutool.core.util.ReflectUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi;
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.*;
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum;
import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum;
import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum;
import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
import cn.iocoder.yudao.module.system.service.logger.LoginLogService;
import cn.iocoder.yudao.module.system.service.member.MemberService;
import cn.iocoder.yudao.module.system.service.oauth2.OAuth2TokenService;
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
import com.anji.captcha.model.common.ResponseModel;
import com.anji.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.Validation;
import javax.validation.Validator;
import static cn.hutool.core.util.RandomUtil.randomEle;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
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 SmsCodeApi smsCodeApi;
@MockBean
private OAuth2TokenService oauth2TokenService;
@MockBean
private MemberService memberService;
@MockBean
private Validator validator;
@BeforeEach
public void setUp() {
authService.setCaptchaEnable(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 验证码正确
authService.setCaptchaEnable(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 = SmsSceneEnum.ADMIN_MEMBER_LOGIN.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 方法(验证码)
doNothing().when(smsCodeApi).useSmsCode((argThat(smsCodeUseReqDTO -> {
assertEquals(mobile, smsCodeUseReqDTO.getMobile());
assertEquals(code, smsCodeUseReqDTO.getCode());
assertEquals(SmsSceneEnum.ADMIN_MEMBER_LOGIN.getScene(), smsCodeUseReqDTO.getScene());
return 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 验证通过
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 验证码关闭
authService.setCaptchaEnable(false);
// 调用,无需断言
authService.validateCaptcha(reqVO);
}
@Test
public void testCaptcha_fail() {
// 准备参数
AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class);
// 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());
}
}

View File

@@ -1,296 +0,0 @@
package cn.iocoder.yudao.module.system.service.dept;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptListReqVO;
import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.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 cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static cn.iocoder.yudao.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());
}
}

View File

@@ -1,248 +0,0 @@
package cn.iocoder.yudao.module.system.service.dept;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO;
import cn.iocoder.yudao.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 cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static cn.iocoder.yudao.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));
}
}

View File

@@ -1,352 +0,0 @@
package cn.iocoder.yudao.module.system.service.dict;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO;
import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictTypeDO;
import cn.iocoder.yudao.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 cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static cn.iocoder.yudao.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("芋艿");
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 是开启
});
}
}

View File

@@ -1,271 +0,0 @@
package cn.iocoder.yudao.module.system.service.dict;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypePageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypeSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictTypeDO;
import cn.iocoder.yudao.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 cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static cn.iocoder.yudao.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("芋艿");
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));
}
}

View File

@@ -1,76 +0,0 @@
package cn.iocoder.yudao.module.system.service.logger;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO;
import cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog.LoginLogPageReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.logger.LoginLogDO;
import cn.iocoder.yudao.module.system.dal.mysql.logger.LoginLogMapper;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Import;
import javax.annotation.Resource;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
import static cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum.CAPTCHA_CODE_ERROR;
import static cn.iocoder.yudao.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);
}
}

View File

@@ -1,114 +0,0 @@
package cn.iocoder.yudao.module.system.service.logger;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.framework.test.core.util.RandomUtils;
import cn.iocoder.yudao.framework.common.biz.system.logger.dto.OperateLogCreateReqDTO;
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogPageReqDTO;
import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO;
import cn.iocoder.yudao.module.system.dal.mysql.logger.OperateLogMapper;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Import;
import javax.annotation.Resource;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
import static cn.iocoder.yudao.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));
}
}

View File

@@ -1,179 +0,0 @@
package cn.iocoder.yudao.module.system.service.mail;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO;
import cn.iocoder.yudao.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 cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static cn.iocoder.yudao.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 芋道源码
*/
@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));
}
}

View File

@@ -1,183 +0,0 @@
package cn.iocoder.yudao.module.system.service.mail;
import cn.hutool.core.map.MapUtil;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.system.controller.admin.mail.vo.log.MailLogPageReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO;
import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailLogDO;
import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO;
import cn.iocoder.yudao.module.system.dal.mysql.mail.MailLogMapper;
import cn.iocoder.yudao.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 cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static org.junit.jupiter.api.Assertions.*;
/**
* {@link MailLogServiceImpl} 的单元测试类
*
* @author 芋道源码
*/
@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();
}
}

View File

@@ -1,329 +0,0 @@
package cn.iocoder.yudao.module.system.service.mail;
import cn.hutool.core.map.MapUtil;
import cn.hutool.extra.mail.*;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
import cn.iocoder.yudao.framework.test.core.util.RandomUtils;
import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO;
import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.mq.message.mail.MailSendMessage;
import cn.iocoder.yudao.module.system.mq.producer.mail.MailProducer;
import cn.iocoder.yudao.module.system.service.member.MemberService;
import cn.iocoder.yudao.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 cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
import static org.junit.jupiter.api.Assertions.*;
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 (final MockedStatic<MailUtil> mailUtilMock = mockStatic(MailUtil.class)) {
// 准备参数
MailSendMessage message = randomPojo(MailSendMessage.class, o -> o.setNickname("芋艿"));
// 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("芋艿 <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("芋艿"));
// 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("芋艿 <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));
}
}
}

View File

@@ -1,215 +0,0 @@
package cn.iocoder.yudao.module.system.service.mail;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplateSaveReqVO;
import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplatePageReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO;
import cn.iocoder.yudao.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 cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.MAIL_TEMPLATE_NOT_EXISTS;
import static org.junit.jupiter.api.Assertions.*;
/**
* {@link MailTemplateServiceImpl} 的单元测试类
*
* @author 芋道源码
*/
@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);
}
}

View File

@@ -1,130 +0,0 @@
package cn.iocoder.yudao.module.system.service.notice;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticePageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticeSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.notice.NoticeDO;
import cn.iocoder.yudao.module.system.dal.mysql.notice.NoticeMapper;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Import;
import javax.annotation.Resource;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
import static cn.iocoder.yudao.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);
}
}

View File

@@ -1,276 +0,0 @@
package cn.iocoder.yudao.module.system.service.notify;
import cn.hutool.core.map.MapUtil;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.system.controller.admin.notify.vo.message.NotifyMessageMyPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.notify.vo.message.NotifyMessagePageReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.notify.NotifyMessageDO;
import cn.iocoder.yudao.module.system.dal.dataobject.notify.NotifyTemplateDO;
import cn.iocoder.yudao.module.system.dal.mysql.notify.NotifyMessageMapper;
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 cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static org.junit.jupiter.api.Assertions.*;
/**
* {@link NotifyMessageServiceImpl} 的单元测试类
*
* @author 芋道源码
*/
@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() {
// 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() {
// 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();
}
}

View File

@@ -1,190 +0,0 @@
package cn.iocoder.yudao.module.system.service.notify;
import cn.hutool.core.map.MapUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
import cn.iocoder.yudao.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 cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.NOTICE_NOT_FOUND;
import static cn.iocoder.yudao.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());
}
}

View File

@@ -1,178 +0,0 @@
package cn.iocoder.yudao.module.system.service.notify;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplatePageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplateSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.notify.NotifyTemplateDO;
import cn.iocoder.yudao.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 cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.NOTIFY_TEMPLATE_NOT_EXISTS;
import static org.junit.jupiter.api.Assertions.*;
/**
* {@link NotifyTemplateServiceImpl} 的单元测试类
*
* @author 芋道源码
*/
@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));
}
}

View File

@@ -1,270 +0,0 @@
package cn.iocoder.yudao.module.system.service.oauth2;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ApproveDO;
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ClientDO;
import cn.iocoder.yudao.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 cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
import static cn.iocoder.yudao.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 芋道源码
*/
@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());
// TODO @芋艿expiresTime 被屏蔽,仅 win11 会复现,建议后续修复。
assertPojoEquals(approve, result.get(0), "expiresTime");
}
@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());
}
}

View File

@@ -1,220 +0,0 @@
package cn.iocoder.yudao.module.system.service.oauth2;
import cn.hutool.extra.spring.SpringUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client.OAuth2ClientPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client.OAuth2ClientSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ClientDO;
import cn.iocoder.yudao.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 cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static cn.iocoder.yudao.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 芋道源码
*/
@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);
}
}
}

View File

@@ -1,101 +0,0 @@
package cn.iocoder.yudao.module.system.service.oauth2;
import cn.hutool.core.util.RandomUtil;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2CodeDO;
import cn.iocoder.yudao.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 cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.OAUTH2_CODE_EXPIRE;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.OAUTH2_CODE_NOT_EXISTS;
import static org.junit.jupiter.api.Assertions.*;
/**
* {@link OAuth2CodeServiceImpl} 的单元测试类
*
* @author 芋道源码
*/
@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());
// TODO @芋艿expiresTime 被屏蔽,仅 win11 会复现,建议后续修复。
assertPojoEquals(codeDO, dbCodeDO, "expiresTime", "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);
// TODO @芋艿expiresTime 被屏蔽,仅 win11 会复现,建议后续修复。
assertPojoEquals(codeDO, result, "expiresTime");
assertNull(oauth2CodeMapper.selectByCode(code));
}
}

View File

@@ -1,173 +0,0 @@
package cn.iocoder.yudao.module.system.service.oauth2;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2CodeDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.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 cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.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 芋道源码
*/
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));
}
}

View File

@@ -1,329 +0,0 @@
package cn.iocoder.yudao.module.system.service.oauth2;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbAndRedisUnitTest;
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.token.OAuth2AccessTokenPageReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ClientDO;
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2RefreshTokenDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.oauth2.OAuth2AccessTokenMapper;
import cn.iocoder.yudao.module.system.dal.mysql.oauth2.OAuth2RefreshTokenMapper;
import cn.iocoder.yudao.module.system.dal.redis.oauth2.OAuth2AccessTokenRedisDAO;
import cn.iocoder.yudao.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 cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.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 芋道源码
*/
@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());
// TODO @芋艿expiresTime 被屏蔽,仅 win11 会复现,建议后续修复。
assertPojoEquals(accessTokenDO, dbAccessTokenDO, "expiresTime", "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());
// TODO @芋艿expiresTime 被屏蔽,仅 win11 会复现,建议后续修复。
assertPojoEquals(accessTokenDO, redisAccessTokenDO, "expiresTime", "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, oauth2AccessTokenMapper.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, o ->
o.setRefreshToken(refreshToken).setClientId(clientId)
.setExpiresTime(LocalDateTime.now().plusDays(1))
.setUserType(UserTypeEnum.ADMIN.getValue())
.setTenantId(TenantContextHolder.getTenantId()));
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());
// TODO @芋艿expiresTime 被屏蔽,仅 win11 会复现,建议后续修复。
assertPojoEquals(newAccessTokenDO, dbAccessTokenDO, "expiresTime", "createTime", "updateTime", "deleted");
assertPojoEquals(newAccessTokenDO, refreshTokenDO, "id", "expiresTime", "createTime", "updateTime", "deleted",
"creator", "updater");
assertFalse(DateUtils.isExpired(newAccessTokenDO.getExpiresTime()));
// 断言,新的访问令牌的缓存
OAuth2AccessTokenDO redisAccessTokenDO = oauth2AccessTokenRedisDAO.get(newAccessTokenDO.getAccessToken());
// TODO @芋艿expiresTime 被屏蔽,仅 win11 会复现,建议后续修复。
assertPojoEquals(newAccessTokenDO, redisAccessTokenDO, "expiresTime", "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);
// 断言
// TODO @芋艿expiresTime 被屏蔽,仅 win11 会复现,建议后续修复。
assertPojoEquals(accessTokenDO, result, "expiresTime", "createTime", "updateTime", "deleted",
"creator", "updater");
// TODO @芋艿expiresTime 被屏蔽,仅 win11 会复现,建议后续修复。
assertPojoEquals(accessTokenDO, oauth2AccessTokenRedisDAO.get(accessToken), "expiresTime", "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_refreshToken() {
// mock 数据(访问令牌)
OAuth2RefreshTokenDO refreshTokenDO = randomPojo(OAuth2RefreshTokenDO.class)
.setExpiresTime(LocalDateTime.now().plusDays(1));
oauth2RefreshTokenMapper.insert(refreshTokenDO);
// 准备参数
String accessToken = refreshTokenDO.getRefreshToken();
// 调研,并断言
OAuth2AccessTokenDO result = oauth2TokenService.getAccessToken(accessToken);
// 断言
assertPojoEquals(refreshTokenDO, result, "expiresTime", "createTime", "updateTime", "deleted",
"creator", "updater");
}
@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);
// 断言
// TODO @芋艿expiresTime 被屏蔽,仅 win11 会复现,建议后续修复。
assertPojoEquals(accessTokenDO, result, "expiresTime", "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());
// TODO @芋艿expiresTime 被屏蔽,仅 win11 会复现,建议后续修复。
assertPojoEquals(accessTokenDO, result, "expiresTime", "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());
// TODO @芋艿expiresTime 被屏蔽,仅 win11 会复现,建议后续修复。
assertPojoEquals(dbAccessToken, pageResult.getList().get(0), "expiresTime");
}
}

View File

@@ -1,331 +0,0 @@
package cn.iocoder.yudao.module.system.service.permission;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuListReqVO;
import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuSaveVO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
import cn.iocoder.yudao.module.system.dal.mysql.permission.MenuMapper;
import cn.iocoder.yudao.module.system.enums.permission.MenuTypeEnum;
import cn.iocoder.yudao.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 cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO.ID_ROOT;
import static cn.iocoder.yudao.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("芋艿").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_Name_success() {
// mock 父子菜单
MenuDO sonMenu = createParentAndSonMenu();
// 准备参数
Long parentId = sonMenu.getParentId();
Long otherSonMenuId = randomLongId();
String otherSonMenuName = randomString();
// 调用,无需断言
menuService.validateMenuName(parentId, otherSonMenuName, otherSonMenuId);
}
@Test
public void testValidateMenu_sonMenuNameNameDuplicate() {
// mock 父子菜单
MenuDO sonMenu = createParentAndSonMenu();
// 准备参数
Long parentId = sonMenu.getParentId();
Long otherSonMenuId = randomLongId();
String otherSonMenuName = sonMenu.getName(); //相同名称
// 调用,并断言异常
assertServiceException(() -> menuService.validateMenuName(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));
}
}

View File

@@ -1,527 +0,0 @@
package cn.iocoder.yudao.module.system.service.permission;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.framework.common.biz.system.permission.dto.DeptDataPermissionRespDTO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleMenuDO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.UserRoleDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.permission.RoleMenuMapper;
import cn.iocoder.yudao.module.system.dal.mysql.permission.UserRoleMapper;
import cn.iocoder.yudao.module.system.enums.permission.DataScopeEnum;
import cn.iocoder.yudao.module.system.service.dept.DeptService;
import cn.iocoder.yudao.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 cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
import static cn.iocoder.yudao.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()));
}
}
}

View File

@@ -1,372 +0,0 @@
package cn.iocoder.yudao.module.system.service.permission;
import cn.hutool.extra.spring.SpringUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RolePageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
import cn.iocoder.yudao.module.system.dal.mysql.permission.RoleMapper;
import cn.iocoder.yudao.module.system.enums.permission.DataScopeEnum;
import cn.iocoder.yudao.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 cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static cn.iocoder.yudao.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 被赋值
.setStatus(randomCommonStatus());
// 调用
Long roleId = roleService.createRole(reqVO, null);
// 断言
RoleDO roleDO = roleMapper.selectById(roleId);
assertPojoEquals(reqVO, roleDO, "id");
assertEquals(RoleTypeEnum.CUSTOM.getType(), roleDO.getType());
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)
.setStatus(randomCommonStatus()));
// 调用
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());
}
}

View File

@@ -1,217 +0,0 @@
package cn.iocoder.yudao.module.system.service.sms;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.system.framework.sms.core.client.SmsClient;
import cn.iocoder.yudao.module.system.framework.sms.core.client.SmsClientFactory;
import cn.iocoder.yudao.module.system.framework.sms.core.property.SmsChannelProperties;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO;
import cn.iocoder.yudao.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 cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SMS_CHANNEL_HAS_CHILDREN;
import static cn.iocoder.yudao.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");
}
@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);
}
@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));
}
@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("芋道源码");
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);
// 准备参数
Long id = channel.getId();
// mock 方法
SmsClient mockClient = mock(SmsClient.class);
SmsChannelProperties properties = BeanUtils.toBean(channel, SmsChannelProperties.class);
when(smsClientFactory.createOrUpdateSmsClient(eq(properties))).thenReturn(mockClient);
// 调用
SmsClient client = smsChannelService.getSmsClient(id);
// 断言
assertSame(client, mockClient);
}
@Test
public void testGetSmsClient_code() {
// 准备参数
String code = randomString();
// mock 方法
SmsClient mockClient = mock(SmsClient.class);
when(smsClientFactory.getSmsClient(eq(code))).thenReturn(mockClient);
// 调用
SmsClient client = smsChannelService.getSmsClient(code);
// 断言
assertSame(client, mockClient);
}
}

View File

@@ -1,191 +0,0 @@
package cn.iocoder.yudao.module.system.service.sms;
import cn.hutool.core.map.MapUtil;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeSendReqDTO;
import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeValidateReqDTO;
import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsCodeDO;
import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsCodeMapper;
import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum;
import cn.iocoder.yudao.module.system.framework.sms.config.SmsCodeProperties;
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 cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
import static cn.iocoder.yudao.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());
});
// 调用
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());
});
// 调用,并断言异常
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());
});
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());
});
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());
});
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());
});
// 调用,并断言异常
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());
});
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());
});
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);
}
}

View File

@@ -1,190 +0,0 @@
package cn.iocoder.yudao.module.system.service.sms;
import cn.hutool.core.map.MapUtil;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogPageReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsLogDO;
import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO;
import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsLogMapper;
import cn.iocoder.yudao.module.system.enums.sms.SmsReceiveStatusEnum;
import cn.iocoder.yudao.module.system.enums.sms.SmsSendStatusEnum;
import cn.iocoder.yudao.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 cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.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();
}
}

View File

@@ -1,298 +0,0 @@
package cn.iocoder.yudao.module.system.service.sms;
import cn.hutool.core.map.MapUtil;
import cn.iocoder.yudao.framework.common.core.KeyValue;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.module.system.framework.sms.core.client.SmsClient;
import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO;
import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsSendRespDTO;
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO;
import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.mq.message.sms.SmsSendMessage;
import cn.iocoder.yudao.module.system.mq.producer.sms.SmsProducer;
import cn.iocoder.yudao.module.system.service.member.MemberService;
import cn.iocoder.yudao.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 cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static cn.iocoder.yudao.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())));
}
}

View File

@@ -1,348 +0,0 @@
package cn.iocoder.yudao.module.system.service.sms;
import cn.hutool.core.map.MapUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
import cn.iocoder.yudao.module.system.framework.sms.core.client.SmsClient;
import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO;
import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplatePageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO;
import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO;
import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsTemplateMapper;
import cn.iocoder.yudao.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 cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static cn.iocoder.yudao.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("芋道源码");
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));
}
}

View File

@@ -1,236 +0,0 @@
package cn.iocoder.yudao.module.system.service.tenant;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackagePageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO;
import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantPackageDO;
import cn.iocoder.yudao.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 cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static cn.iocoder.yudao.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 芋道源码
*/
@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("芋道源码");
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));
}
}

View File

@@ -1,458 +0,0 @@
package cn.iocoder.yudao.module.system.service.tenant;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.tenant.config.TenantProperties;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO;
import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantPackageDO;
import cn.iocoder.yudao.module.system.dal.mysql.tenant.TenantMapper;
import cn.iocoder.yudao.module.system.enums.permission.RoleCodeEnum;
import cn.iocoder.yudao.module.system.enums.permission.RoleTypeEnum;
import cn.iocoder.yudao.module.system.service.permission.MenuService;
import cn.iocoder.yudao.module.system.service.permission.PermissionService;
import cn.iocoder.yudao.module.system.service.permission.RoleService;
import cn.iocoder.yudao.module.system.service.tenant.handler.TenantInfoHandler;
import cn.iocoder.yudao.module.system.service.tenant.handler.TenantMenuHandler;
import cn.iocoder.yudao.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 cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO.PACKAGE_ID_SYSTEM;
import static cn.iocoder.yudao.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 芋道源码
*/
@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.iocoder.cn");
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("芋道源码");
o.setContactName("芋艿");
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.iocoder.cn"));
tenantMapper.insert(dbTenant);// @Sql: 先插入出一条存在的数据
// 调用
TenantDO result = tenantService.getTenantByWebsite("https://www.iocoder.cn");
// 校验存在
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));
}
}

View File

@@ -1,763 +0,0 @@
package cn.iocoder.yudao.module.system.service.user;
import cn.hutool.core.util.RandomUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.infra.api.config.ConfigApi;
import cn.iocoder.yudao.module.infra.api.file.FileApi;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserImportExcelVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserImportRespVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.UserPostDO;
import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.dept.UserPostMapper;
import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper;
import cn.iocoder.yudao.module.system.enums.common.SexEnum;
import cn.iocoder.yudao.module.system.service.dept.DeptService;
import cn.iocoder.yudao.module.system.service.dept.PostService;
import cn.iocoder.yudao.module.system.service.permission.PermissionService;
import cn.iocoder.yudao.module.system.service.tenant.TenantService;
import org.junit.jupiter.api.BeforeEach;
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.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import static cn.hutool.core.util.RandomUtil.randomEle;
import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.module.system.service.user.AdminUserServiceImpl.USER_INIT_PASSWORD_KEY;
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;
@MockBean
private ConfigApi configApi;
@BeforeEach
public void before() {
// mock 初始化密码
when(configApi.getConfigValueByKey(USER_INIT_PASSWORD_KEY)).thenReturn("yudaoyuanma");
}
@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("yudaoyuanma");
// 调用
Long userId = userService.createUser(reqVO);
// 断言
AdminUserDO user = userMapper.selectById(userId);
assertPojoEquals(reqVO, user, "password", "id");
assertEquals("yudaoyuanma", 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());
o.setAvatar(randomURL());
});
// 调用
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 testUpdateUserPassword02_success() {
// mock 数据
AdminUserDO dbUser = randomAdminUserDO();
userMapper.insert(dbUser);
// 准备参数
Long userId = dbUser.getId();
String password = "yudao";
// 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 -> {
o.setEmail(randomEmail());
o.setMobile(randomMobile());
});
// 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 的范围
o.setEmail(randomEmail());
o.setMobile(randomMobile());
});
// 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("yudaoyuanma"))).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());
o.setEmail(randomEmail());
o.setMobile(randomMobile());
});
// 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());
o.setEmail(randomEmail());
o.setMobile(randomMobile());
});
// 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));
}
}