- Playwright 테스트 정리용 internal API 추가
- /internal/test-cleanup/{org,user,orphans} 신설
- dev 프로필 전용, 토큰+IP allowlist 이중 가드
- 13개 고아 테이블 cascade/스윕 삭제 서비스
- 리포지토리 deleteBy 메서드 추가, 단위테스트 포함
This commit is contained in:
+55
@@ -0,0 +1,55 @@
|
||||
package com.eactive.apim.portal.djb.testcleanup.service;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.Query;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.mockito.junit.jupiter.MockitoSettings;
|
||||
import org.mockito.quality.Strictness;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.Profiles;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
@MockitoSettings(strictness = Strictness.LENIENT)
|
||||
class OrphanCleanupServiceTest {
|
||||
|
||||
@Mock private Environment environment;
|
||||
@Mock private EntityManager entityManager;
|
||||
@Mock private Query query;
|
||||
|
||||
private OrphanCleanupService service;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
service = new OrphanCleanupService(environment);
|
||||
ReflectionTestUtils.setField(service, "entityManager", entityManager);
|
||||
when(environment.acceptsProfiles(Profiles.of("stage", "prod"))).thenReturn(false);
|
||||
when(entityManager.createNativeQuery(org.mockito.ArgumentMatchers.anyString())).thenReturn(query);
|
||||
when(query.executeUpdate()).thenReturn(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
void sweep_runsAllThirteenTablesAndReportsCounts() {
|
||||
when(query.executeUpdate()).thenReturn(3);
|
||||
|
||||
TestCleanupResult result = service.sweep();
|
||||
|
||||
assertEquals(13, result.getDeletedCounts().size());
|
||||
result.getDeletedCounts().values().forEach(count -> assertEquals(3L, count));
|
||||
}
|
||||
|
||||
@Test
|
||||
void sweep_prodProfile_throws() {
|
||||
when(environment.acceptsProfiles(Profiles.of("stage", "prod"))).thenReturn(true);
|
||||
|
||||
assertThrows(IllegalStateException.class, () -> service.sweep());
|
||||
}
|
||||
}
|
||||
+194
@@ -0,0 +1,194 @@
|
||||
package com.eactive.apim.portal.djb.testcleanup.service;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.eactive.apim.portal.app.repository.CredentialRepository;
|
||||
import com.eactive.apim.portal.apps.community.partnership.repository.PartnershipApplicationRepository;
|
||||
import com.eactive.apim.portal.apps.community.qna.repository.InquiryRepository;
|
||||
import com.eactive.apim.portal.apps.user.repository.PortalOrgRepository;
|
||||
import com.eactive.apim.portal.djb.community.qna.comment.repository.InquiryCommentRepository;
|
||||
import com.eactive.apim.portal.djb.webhook.repository.WebhookRequestApiRepository;
|
||||
import com.eactive.apim.portal.djb.webhook.repository.WebhookRequestEventRepository;
|
||||
import com.eactive.apim.portal.djb.webhook.repository.WebhookRequestRepository;
|
||||
import com.eactive.apim.portal.djb.webhook.repository.entity.WebhookRequest;
|
||||
import com.eactive.apim.portal.djb.webhook.service.WebhookService;
|
||||
import com.eactive.apim.portal.portalorg.entity.PortalOrg;
|
||||
import com.eactive.apim.portal.portaluser.entity.PortalUser;
|
||||
import com.eactive.apim.portal.portaluser.repository.PortalUserPrivacyAgreementRepository;
|
||||
import com.eactive.apim.portal.portaluser.repository.PortalUserRepository;
|
||||
import com.eactive.apim.portal.portaluser.repository.UserPasswordHistoryRepository;
|
||||
import com.eactive.apim.portal.portaluser.repository.UserRoleHistoryRepository;
|
||||
import com.eactive.apim.portal.user.repository.UserLogRepository;
|
||||
import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.mockito.junit.jupiter.MockitoSettings;
|
||||
import org.mockito.quality.Strictness;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.Profiles;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
@MockitoSettings(strictness = Strictness.LENIENT)
|
||||
class TestCleanupServiceTest {
|
||||
|
||||
@Mock private Environment environment;
|
||||
@Mock private PortalOrgRepository portalOrgRepository;
|
||||
@Mock private PortalUserRepository portalUserRepository;
|
||||
@Mock private InquiryRepository inquiryRepository;
|
||||
@Mock private InquiryCommentRepository inquiryCommentRepository;
|
||||
@Mock private PartnershipApplicationRepository partnershipApplicationRepository;
|
||||
@Mock private UserRoleHistoryRepository userRoleHistoryRepository;
|
||||
@Mock private PortalUserPrivacyAgreementRepository portalUserPrivacyAgreementRepository;
|
||||
@Mock private UserPasswordHistoryRepository userPasswordHistoryRepository;
|
||||
@Mock private UserLogRepository userLogRepository;
|
||||
@Mock private CredentialRepository credentialRepository;
|
||||
@Mock private WebhookRequestRepository webhookRequestRepository;
|
||||
@Mock private WebhookRequestApiRepository webhookRequestApiRepository;
|
||||
@Mock private WebhookRequestEventRepository webhookRequestEventRepository;
|
||||
@Mock private WebhookService webhookService;
|
||||
@Mock private TestCleanupNativeQueries nativeQueries;
|
||||
|
||||
private TestCleanupService service;
|
||||
|
||||
private static final String ORG_ID = "ORG1";
|
||||
private static final String USER_ID = "USER1";
|
||||
private static final String LOGIN_ID = "user1@test.com";
|
||||
private static final String COMP_REG_NO = "1234567890";
|
||||
private static final String EMAIL = "user1@test.com";
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
service = new TestCleanupService(environment, portalOrgRepository, portalUserRepository,
|
||||
inquiryRepository, inquiryCommentRepository, partnershipApplicationRepository,
|
||||
userRoleHistoryRepository, portalUserPrivacyAgreementRepository, userPasswordHistoryRepository,
|
||||
userLogRepository, credentialRepository, webhookRequestRepository, webhookRequestApiRepository,
|
||||
webhookRequestEventRepository, webhookService, nativeQueries);
|
||||
when(environment.acceptsProfiles(Profiles.of("stage", "prod"))).thenReturn(false);
|
||||
}
|
||||
|
||||
private PortalUser user() {
|
||||
PortalUser u = new PortalUser();
|
||||
u.setId(USER_ID);
|
||||
u.setLoginId(LOGIN_ID);
|
||||
return u;
|
||||
}
|
||||
|
||||
@Test
|
||||
void deleteOrgCascade_notFound() {
|
||||
when(portalOrgRepository.findByCompRegNo(COMP_REG_NO)).thenReturn(Optional.empty());
|
||||
|
||||
TestCleanupResult result = service.deleteOrgCascade(COMP_REG_NO);
|
||||
|
||||
assertFalse(result.isFound());
|
||||
assertTrue(result.getDeletedCounts().isEmpty());
|
||||
verifyNoInteractions(webhookService, portalUserRepository);
|
||||
}
|
||||
|
||||
@Test
|
||||
void deleteOrgCascade_found_cascadesUsersAndOrg() {
|
||||
PortalOrg org = org();
|
||||
PortalUser member = user();
|
||||
when(portalOrgRepository.findByCompRegNo(COMP_REG_NO)).thenReturn(Optional.of(org));
|
||||
when(portalUserRepository.findAllByPortalOrg_Id(ORG_ID)).thenReturn(Collections.singletonList(member));
|
||||
when(webhookRequestRepository.findByOrgId(ORG_ID)).thenReturn(Optional.empty());
|
||||
when(nativeQueries.deleteCredentialApiByOrgId(ORG_ID)).thenReturn(2);
|
||||
when(credentialRepository.deleteByOrgid(ORG_ID)).thenReturn(1L);
|
||||
|
||||
TestCleanupResult result = service.deleteOrgCascade(COMP_REG_NO);
|
||||
|
||||
assertTrue(result.isFound());
|
||||
assertEquals(ORG_ID, result.getTargetId());
|
||||
assertEquals(1L, result.getDeletedCounts().get("PTL_USER"));
|
||||
assertEquals(2L, result.getDeletedCounts().get("PTL_CREDENTIAL_API"));
|
||||
assertEquals(1L, result.getDeletedCounts().get("PTL_CREDENTIAL"));
|
||||
assertEquals(1L, result.getDeletedCounts().get("PTL_ORG"));
|
||||
assertEquals(0L, result.getDeletedCounts().get("PTL_WEBHOOK_REQ"));
|
||||
verify(inquiryCommentRepository).deleteByInquiry_Inquirer_Id(USER_ID);
|
||||
verify(inquiryRepository).deleteByInquirer_Id(USER_ID);
|
||||
verify(userRoleHistoryRepository).deleteByUserId(LOGIN_ID);
|
||||
verify(userPasswordHistoryRepository).deleteByUserId(USER_ID);
|
||||
verify(portalUserRepository).delete(member);
|
||||
verify(webhookService, never()).delete(anyLong(), anyString());
|
||||
verify(portalOrgRepository).delete(org);
|
||||
}
|
||||
|
||||
@Test
|
||||
void deleteOrgCascade_withWebhook_delegatesToWebhookService() {
|
||||
PortalOrg org = org();
|
||||
WebhookRequest webhook = new WebhookRequest();
|
||||
webhook.setId(99L);
|
||||
when(portalOrgRepository.findByCompRegNo(COMP_REG_NO)).thenReturn(Optional.of(org));
|
||||
when(portalUserRepository.findAllByPortalOrg_Id(ORG_ID)).thenReturn(Collections.emptyList());
|
||||
when(webhookRequestRepository.findByOrgId(ORG_ID)).thenReturn(Optional.of(webhook));
|
||||
when(webhookRequestApiRepository.findByWebhookReqId(99L)).thenReturn(Collections.emptyList());
|
||||
when(webhookRequestEventRepository.findByWebhookReqId(99L)).thenReturn(Collections.emptyList());
|
||||
|
||||
TestCleanupResult result = service.deleteOrgCascade(COMP_REG_NO);
|
||||
|
||||
verify(webhookService, times(1)).delete(99L, ORG_ID);
|
||||
assertEquals(1L, result.getDeletedCounts().get("PTL_WEBHOOK_REQ"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void deleteUserCascade_notFound() {
|
||||
when(portalUserRepository.findPortalUserByEmailAddr(EMAIL)).thenReturn(Optional.empty());
|
||||
|
||||
TestCleanupResult result = service.deleteUserCascade(EMAIL);
|
||||
|
||||
assertFalse(result.isFound());
|
||||
assertTrue(result.getDeletedCounts().isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void deleteUserCascade_found_deletesOrphanDataAndUser() {
|
||||
PortalUser target = user();
|
||||
when(portalUserRepository.findPortalUserByEmailAddr(EMAIL)).thenReturn(Optional.of(target));
|
||||
|
||||
TestCleanupResult result = service.deleteUserCascade(EMAIL);
|
||||
|
||||
assertTrue(result.isFound());
|
||||
assertEquals(USER_ID, result.getTargetId());
|
||||
verify(inquiryCommentRepository).deleteByInquiry_Inquirer_Id(USER_ID);
|
||||
verify(inquiryRepository).deleteByInquirer_Id(USER_ID);
|
||||
verify(partnershipApplicationRepository).deleteByCreatedBy(USER_ID);
|
||||
verify(userRoleHistoryRepository).deleteByUserId(LOGIN_ID);
|
||||
verify(portalUserPrivacyAgreementRepository).deleteByCreatedBy(USER_ID);
|
||||
verify(userPasswordHistoryRepository).deleteByUserId(USER_ID);
|
||||
verify(userLogRepository).deleteByLoginId(LOGIN_ID);
|
||||
verify(portalUserRepository).delete(target);
|
||||
}
|
||||
|
||||
@Test
|
||||
void deleteOrgCascade_prodProfile_throws() {
|
||||
when(environment.acceptsProfiles(Profiles.of("stage", "prod"))).thenReturn(true);
|
||||
|
||||
assertThrows(IllegalStateException.class, () -> service.deleteOrgCascade(COMP_REG_NO));
|
||||
}
|
||||
|
||||
@Test
|
||||
void deleteUserCascade_prodProfile_throws() {
|
||||
when(environment.acceptsProfiles(Profiles.of("stage", "prod"))).thenReturn(true);
|
||||
|
||||
assertThrows(IllegalStateException.class, () -> service.deleteUserCascade(EMAIL));
|
||||
}
|
||||
|
||||
private PortalOrg org() {
|
||||
PortalOrg o = new PortalOrg();
|
||||
o.setId(ORG_ID);
|
||||
return o;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user