package com.ruoyi.user.service.impl;
|
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.when;
|
|
import org.junit.jupiter.api.DisplayName;
|
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.mockito.ArgumentCaptor;
|
import org.mockito.InjectMocks;
|
import org.mockito.Mock;
|
import org.mockito.junit.jupiter.MockitoExtension;
|
import com.ruoyi.common.core.exception.ServiceException;
|
import com.ruoyi.user.domain.AccountCertificationApply;
|
import com.ruoyi.user.domain.AccountUser;
|
import com.ruoyi.user.domain.dto.CompanyCertificationApplyDto;
|
import com.ruoyi.user.domain.vo.AccountCertificationStatusVo;
|
import com.ruoyi.user.domain.vo.CompanyCertificationStatusVo;
|
import com.ruoyi.user.mapper.AccountCertificationApplyMapper;
|
import com.ruoyi.user.mapper.AccountCertificationMapper;
|
import com.ruoyi.user.mapper.AccountUserMapper;
|
|
/**
|
* 会员主体认证申请 服务单元测试
|
*
|
* 覆盖 C 端个人主体认证提交:正常提交(落待审核申请 + 联动认证状态为审核中)、
|
* 待审核申请存在时防重拒绝、以及会员ID/姓名/身份证号缺失时的入参校验;
|
* 另覆盖认证状态查询:有申请时回填资料与驳回原因、无申请/无登录态时返回空对象。
|
*
|
* @author hugray
|
*/
|
@ExtendWith(MockitoExtension.class)
|
class AccountCertificationApplyServiceImplTest
|
{
|
private static final Long USER_ID = 66L;
|
|
private static final String REAL_NAME = "张三";
|
|
private static final String ID_CARD = "110101199003071234";
|
|
@Mock
|
private AccountCertificationApplyMapper certificationApplyMapper;
|
|
@Mock
|
private AccountCertificationMapper certificationMapper;
|
|
@Mock
|
private AccountUserMapper accountUserMapper;
|
|
@InjectMocks
|
private AccountCertificationApplyServiceImpl certificationApplyService;
|
|
@Test
|
@DisplayName("正常提交应落一条待审核的个人申请并把认证状态置为审核中")
|
void submitPersonalCertification_shouldInsertPendingApplyAndSetAuditing()
|
{
|
when(certificationApplyMapper.countPendingPersonalApplyByUserId(USER_ID)).thenReturn(0);
|
when(certificationApplyMapper.insertCertificationApply(any(AccountCertificationApply.class))).thenReturn(1);
|
|
certificationApplyService.submitPersonalCertification(USER_ID, " 张三 ", "11010119900307123x");
|
|
// 申请快照:个人主体、待审核、姓名去空白、身份证号末位小写 x 统一转大写
|
ArgumentCaptor<AccountCertificationApply> applyCaptor = ArgumentCaptor.forClass(AccountCertificationApply.class);
|
verify(certificationApplyMapper).insertCertificationApply(applyCaptor.capture());
|
AccountCertificationApply saved = applyCaptor.getValue();
|
assertEquals(USER_ID, saved.getUserId());
|
assertEquals("1", saved.getSubjectType());
|
assertEquals("0", saved.getAuditStatus());
|
assertEquals(REAL_NAME, saved.getRealName());
|
assertEquals("11010119900307123X", saved.getIdCard());
|
|
// 状态联动:account_user.auth_status = '1'(审核中)
|
ArgumentCaptor<AccountUser> userCaptor = ArgumentCaptor.forClass(AccountUser.class);
|
verify(accountUserMapper).updateUserAuthStatus(userCaptor.capture());
|
assertEquals(USER_ID, userCaptor.getValue().getUserId());
|
assertEquals("1", userCaptor.getValue().getAuthStatus());
|
}
|
|
@Test
|
@DisplayName("已有待审核申请时应拒绝重复提交且不落库")
|
void submitPersonalCertification_shouldThrow_whenPendingApplyExists()
|
{
|
when(certificationApplyMapper.countPendingPersonalApplyByUserId(USER_ID)).thenReturn(1);
|
|
ServiceException ex = assertThrows(ServiceException.class,
|
() -> certificationApplyService.submitPersonalCertification(USER_ID, REAL_NAME, ID_CARD));
|
|
assertEquals("已有实名认证申请正在审核中,请勿重复提交", ex.getMessage());
|
verify(certificationApplyMapper, never()).insertCertificationApply(any(AccountCertificationApply.class));
|
}
|
|
@Test
|
@DisplayName("会员ID为空时应抛出提交失败")
|
void submitPersonalCertification_shouldThrow_whenUserIdNull()
|
{
|
ServiceException ex = assertThrows(ServiceException.class,
|
() -> certificationApplyService.submitPersonalCertification(null, REAL_NAME, ID_CARD));
|
|
assertEquals("提交实名认证失败", ex.getMessage());
|
verify(certificationApplyMapper, never()).insertCertificationApply(any(AccountCertificationApply.class));
|
}
|
|
@Test
|
@DisplayName("姓名为空时应抛出提示且不落库")
|
void submitPersonalCertification_shouldThrow_whenRealNameBlank()
|
{
|
ServiceException ex = assertThrows(ServiceException.class,
|
() -> certificationApplyService.submitPersonalCertification(USER_ID, "", ID_CARD));
|
|
assertEquals("姓名与身份证号不能为空", ex.getMessage());
|
verify(certificationApplyMapper, never()).insertCertificationApply(any(AccountCertificationApply.class));
|
}
|
|
@Test
|
@DisplayName("身份证号为空时应抛出提示且不落库")
|
void submitPersonalCertification_shouldThrow_whenIdCardBlank()
|
{
|
ServiceException ex = assertThrows(ServiceException.class,
|
() -> certificationApplyService.submitPersonalCertification(USER_ID, REAL_NAME, null));
|
|
assertEquals("姓名与身份证号不能为空", ex.getMessage());
|
verify(certificationApplyMapper, never()).insertCertificationApply(any(AccountCertificationApply.class));
|
}
|
|
@Test
|
@DisplayName("查询认证状态应回填最近一次申请的资料与驳回原因")
|
void getCertificationStatus_shouldFillFromLatestApply()
|
{
|
AccountCertificationApply apply = new AccountCertificationApply();
|
apply.setRealName(REAL_NAME);
|
apply.setIdCard(ID_CARD);
|
apply.setAuditStatus("2");
|
apply.setAuditRemark("身份证照片不清晰,请重新提交");
|
when(certificationApplyMapper.selectLatestPersonalApplyByUserId(USER_ID)).thenReturn(apply);
|
|
AccountCertificationStatusVo vo = certificationApplyService.getCertificationStatus(USER_ID);
|
|
assertEquals(REAL_NAME, vo.getRealName());
|
assertEquals(ID_CARD, vo.getIdCard());
|
assertEquals("2", vo.getAuditStatus());
|
assertEquals("身份证照片不清晰,请重新提交", vo.getAuditRemark());
|
}
|
|
@Test
|
@DisplayName("从未提交时查询认证状态应返回空对象而非 null")
|
void getCertificationStatus_shouldReturnEmpty_whenNoApply()
|
{
|
when(certificationApplyMapper.selectLatestPersonalApplyByUserId(USER_ID)).thenReturn(null);
|
|
AccountCertificationStatusVo vo = certificationApplyService.getCertificationStatus(USER_ID);
|
|
assertNull(vo.getRealName());
|
assertNull(vo.getIdCard());
|
assertNull(vo.getAuditStatus());
|
assertNull(vo.getAuditRemark());
|
}
|
|
@Test
|
@DisplayName("会员ID为空时查询认证状态应返回空对象且不查库")
|
void getCertificationStatus_shouldReturnEmpty_whenUserIdNull()
|
{
|
AccountCertificationStatusVo vo = certificationApplyService.getCertificationStatus(null);
|
|
assertNull(vo.getAuditStatus());
|
verify(certificationApplyMapper, never()).selectLatestPersonalApplyByUserId(any());
|
}
|
|
@Test
|
@DisplayName("正常提交应落一条待审核的企业申请并把企业认证状态置为审核中")
|
void submitCompanyCertification_shouldInsertPendingApplyAndSetCompanyAuditing()
|
{
|
when(certificationApplyMapper.countPendingCompanyApplyByUserId(USER_ID)).thenReturn(0);
|
when(certificationApplyMapper.insertCertificationApply(any(AccountCertificationApply.class))).thenReturn(1);
|
|
certificationApplyService.submitCompanyCertification(USER_ID, buildCompanyDto("3", "1", null));
|
|
// 申请快照:企业主体(3)、待审核、无有效期(长期)
|
ArgumentCaptor<AccountCertificationApply> applyCaptor = ArgumentCaptor.forClass(AccountCertificationApply.class);
|
verify(certificationApplyMapper).insertCertificationApply(applyCaptor.capture());
|
AccountCertificationApply saved = applyCaptor.getValue();
|
assertEquals(USER_ID, saved.getUserId());
|
assertEquals("3", saved.getSubjectType());
|
assertEquals("0", saved.getAuditStatus());
|
assertEquals("测试企业有限公司", saved.getCompanyName());
|
|
// 状态联动:account_user.company_auth_status = '1'(审核中),且不动个人 auth_status
|
ArgumentCaptor<AccountUser> userCaptor = ArgumentCaptor.forClass(AccountUser.class);
|
verify(accountUserMapper).updateUserCompanyAuthStatus(userCaptor.capture());
|
assertEquals("1", userCaptor.getValue().getCompanyAuthStatus());
|
verify(accountUserMapper, never()).updateUserAuthStatus(any(AccountUser.class));
|
}
|
|
@Test
|
@DisplayName("有效期选「短期」但未填起止日期时应抛出提示且不落库")
|
void submitCompanyCertification_shouldThrow_whenShortTermPeriodMissing()
|
{
|
ServiceException ex = assertThrows(ServiceException.class,
|
() -> certificationApplyService.submitCompanyCertification(USER_ID, buildCompanyDto("3", "2", null)));
|
|
assertEquals("请选择营业执照有效期起止日期", ex.getMessage());
|
verify(certificationApplyMapper, never()).insertCertificationApply(any(AccountCertificationApply.class));
|
}
|
|
@Test
|
@DisplayName("已有待审核的企业申请时应拒绝重复提交且不落库")
|
void submitCompanyCertification_shouldThrow_whenPendingApplyExists()
|
{
|
when(certificationApplyMapper.countPendingCompanyApplyByUserId(USER_ID)).thenReturn(1);
|
|
ServiceException ex = assertThrows(ServiceException.class,
|
() -> certificationApplyService.submitCompanyCertification(USER_ID, buildCompanyDto("2", "1", null)));
|
|
assertEquals("已有企业认证申请正在审核中,请勿重复提交", ex.getMessage());
|
verify(certificationApplyMapper, never()).insertCertificationApply(any(AccountCertificationApply.class));
|
}
|
|
@Test
|
@DisplayName("会员ID为空时提交企业认证应抛出提交失败")
|
void submitCompanyCertification_shouldThrow_whenUserIdNull()
|
{
|
ServiceException ex = assertThrows(ServiceException.class,
|
() -> certificationApplyService.submitCompanyCertification(null, buildCompanyDto("3", "1", null)));
|
|
assertEquals("提交企业认证失败", ex.getMessage());
|
verify(certificationApplyMapper, never()).insertCertificationApply(any(AccountCertificationApply.class));
|
}
|
|
@Test
|
@DisplayName("查询企业认证状态应回填最近一次申请的资料与驳回原因")
|
void getCompanyCertificationStatus_shouldFillFromLatestApply()
|
{
|
AccountCertificationApply apply = new AccountCertificationApply();
|
apply.setSubjectType("3");
|
apply.setCompanyName("测试企业有限公司");
|
apply.setAuditStatus("2");
|
apply.setAuditRemark("营业执照照片不清晰,请重新提交");
|
when(certificationApplyMapper.selectLatestCompanyApplyByUserId(USER_ID)).thenReturn(apply);
|
|
CompanyCertificationStatusVo vo = certificationApplyService.getCompanyCertificationStatus(USER_ID);
|
|
assertEquals("3", vo.getSubjectType());
|
assertEquals("测试企业有限公司", vo.getCompanyName());
|
assertEquals("2", vo.getAuditStatus());
|
assertEquals("营业执照照片不清晰,请重新提交", vo.getAuditRemark());
|
}
|
|
@Test
|
@DisplayName("从未提交企业认证时查询状态应返回空对象而非 null")
|
void getCompanyCertificationStatus_shouldReturnEmpty_whenNoApply()
|
{
|
when(certificationApplyMapper.selectLatestCompanyApplyByUserId(USER_ID)).thenReturn(null);
|
|
CompanyCertificationStatusVo vo = certificationApplyService.getCompanyCertificationStatus(USER_ID);
|
|
assertNull(vo.getCompanyName());
|
assertNull(vo.getAuditStatus());
|
assertNull(vo.getAuditRemark());
|
}
|
|
/** 构造一份字段齐全的企业认证入参:validType 控制营业执照有效期类型,licensePeriod 为起止日期 */
|
private CompanyCertificationApplyDto buildCompanyDto(String subjectType, String validType, String licensePeriod)
|
{
|
CompanyCertificationApplyDto dto = new CompanyCertificationApplyDto();
|
dto.setSubjectType(subjectType);
|
dto.setCompanyName("测试企业有限公司");
|
dto.setLicenseImage("/upload/license.png");
|
dto.setCreditCode("91310000MA1FL0XXXX");
|
dto.setLicenseValidType(validType);
|
dto.setLicenseValidPeriod(licensePeriod);
|
dto.setRegisteredRegion("上海市 上海市 浦东新区");
|
dto.setCompanyAddress("浦东新区世纪大道 1 号");
|
dto.setLegalPerson("李四");
|
dto.setLegalIdCardFront("/upload/id-front.png");
|
dto.setLegalIdCardBack("/upload/id-back.png");
|
dto.setLegalIdValidType("1");
|
dto.setLegalIdValidPeriod(null);
|
dto.setLegalIdAddress("浦东新区世纪大道 1 号");
|
dto.setContactName("王五");
|
dto.setContactPhone("13800000000");
|
dto.setContactEmail("test@example.com");
|
dto.setPayeeType("1");
|
dto.setBankCardImage("/upload/bank.png");
|
dto.setBankCardNo("6222020000000000000");
|
dto.setBankCity("上海市");
|
return dto;
|
}
|
}
|