From 89cce0f078b728a04d15ae687cef47063b9e1e85 Mon Sep 17 00:00:00 2001 From: Sihun23 Date: Wed, 5 Feb 2025 14:33:58 +0900 Subject: [PATCH 1/3] =?UTF-8?q?CLAP-276=20fix:Member.createMember=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=ED=95=B4=EC=84=9C=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../outbound/persistense/entity/member/MemberEntity.java | 1 + .../server/application/service/admin/CsvParseService.java | 6 ++++-- .../service/admin/RegisterMemberCSVService.java | 7 +++++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/main/java/clap/server/adapter/outbound/persistense/entity/member/MemberEntity.java b/src/main/java/clap/server/adapter/outbound/persistense/entity/member/MemberEntity.java index c2e28dca..40e294a8 100644 --- a/src/main/java/clap/server/adapter/outbound/persistense/entity/member/MemberEntity.java +++ b/src/main/java/clap/server/adapter/outbound/persistense/entity/member/MemberEntity.java @@ -46,6 +46,7 @@ public class MemberEntity extends BaseTimeEntity { @Column(nullable = false) private MemberStatus status; + @Column private String password; @Column diff --git a/src/main/java/clap/server/application/service/admin/CsvParseService.java b/src/main/java/clap/server/application/service/admin/CsvParseService.java index aeaed78c..547b99c0 100644 --- a/src/main/java/clap/server/application/service/admin/CsvParseService.java +++ b/src/main/java/clap/server/application/service/admin/CsvParseService.java @@ -65,12 +65,14 @@ private Member mapToMember(String[] fields, List departments) { fields[0].trim(), // name fields[4].trim(), // email fields[1].trim(), // nickname - Boolean.parseBoolean(fields[6].trim()), // isReviewer + Boolean.parseBoolean(fields[6].trim().toLowerCase()), // isReviewer department, // department MemberRole.valueOf(fields[5].trim()), // role fields[3].trim() // departmentRole ); - return toMember(memberInfo); + return Member.builder() + .memberInfo(memberInfo) + .build(); } } diff --git a/src/main/java/clap/server/application/service/admin/RegisterMemberCSVService.java b/src/main/java/clap/server/application/service/admin/RegisterMemberCSVService.java index 76261543..0723c7dd 100644 --- a/src/main/java/clap/server/application/service/admin/RegisterMemberCSVService.java +++ b/src/main/java/clap/server/application/service/admin/RegisterMemberCSVService.java @@ -23,9 +23,12 @@ public class RegisterMemberCSVService implements RegisterMemberCSVUsecase { public int registerMembersFromCsv(Long adminId, MultipartFile file) { List members = csvParser.parseDataAndMapToMember(file); Member admin = memberService.findActiveMember(adminId); - members.forEach(member -> {member.register(admin);}); - commandMemberPort.saveAll(members); + List newMembers = members.stream() + .map(memberData -> Member.createMember(admin, memberData.getMemberInfo())) + .toList(); + + commandMemberPort.saveAll(newMembers); return members.size(); } } \ No newline at end of file From 9660b2a9990ee4acea9217f7a282a5a48eaf0a43 Mon Sep 17 00:00:00 2001 From: Sihun23 Date: Wed, 5 Feb 2025 14:41:14 +0900 Subject: [PATCH 2/3] =?UTF-8?q?CLAP-284=20fix:RegisterMemberCSVService=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=EC=97=90=20=EB=94=B0=EB=A5=B8=20test=20code?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/RegisterMemberCSVServiceTest.java | 75 ++++++++----------- 1 file changed, 33 insertions(+), 42 deletions(-) diff --git a/src/test/java/clap/server/application/service/admin/RegisterMemberCSVServiceTest.java b/src/test/java/clap/server/application/service/admin/RegisterMemberCSVServiceTest.java index 3c974e35..165a3cbb 100644 --- a/src/test/java/clap/server/application/service/admin/RegisterMemberCSVServiceTest.java +++ b/src/test/java/clap/server/application/service/admin/RegisterMemberCSVServiceTest.java @@ -12,7 +12,6 @@ import org.springframework.mock.web.MockMultipartFile; import org.springframework.web.multipart.MultipartFile; -import java.io.IOException; import java.util.List; import static org.junit.jupiter.api.Assertions.*; @@ -25,7 +24,6 @@ class RegisterMemberCSVServiceTest { private CommandMemberPort commandMemberPort; private CsvParseService csvParseService; - @BeforeEach void setup() { memberService = Mockito.mock(MemberService.class); @@ -35,30 +33,30 @@ void setup() { } /** - * 정상적인 회원 등록 테스트 - * - 주어진 CSV 파일을 정상적으로 파싱하여 회원이 등록되는지 검증 + * ✅ 정상적인 회원 등록 테스트 */ @Test @DisplayName("CSV 파일에서 회원 정보를 성공적으로 파싱하고 등록하는지 검증한다.") void testRegisterMembersFromCsvSuccess() { Long adminId = 1L; - MultipartFile file = new MockMultipartFile("file", "members.csv", "text/csv", "dummy-content".getBytes()); + MultipartFile file = new MockMultipartFile("file", "members.csv", "text/csv", "name,nickname,departmentId,departmentRole,email,role,isReviewer\nJohn,JohnDoe,1,Manager,john.doe@example.com,ROLE_USER,TRUE".getBytes()); Member admin = Mockito.mock(Member.class); - List parsedMembers = List.of(Mockito.mock(Member.class), Mockito.mock(Member.class)); + Member member1 = Mockito.mock(Member.class); + Member member2 = Mockito.mock(Member.class); + List parsedMembers = List.of(member1, member2); when(memberService.findActiveMember(adminId)).thenReturn(admin); when(csvParseService.parseDataAndMapToMember(file)).thenReturn(parsedMembers); int addedCount = registerMemberCSVService.registerMembersFromCsv(adminId, file); - assertEquals(2, addedCount); - verify(commandMemberPort).saveAll(parsedMembers); - verify(parsedMembers.get(0)).register(admin); - verify(parsedMembers.get(1)).register(admin); + assertEquals(2, addedCount); // 2명이 성공적으로 등록됨 + verify(commandMemberPort).saveAll(parsedMembers); // 모든 회원 저장 + verify(member1).register(admin); // 관리자와 연결 + verify(member2).register(admin); // 관리자와 연결 } - /** * ❌ 관리자 찾기 실패 (MEMBER_NOT_FOUND) */ @@ -74,9 +72,8 @@ void testRegisterMembersFromCsvThrowsWhenAdminNotFound() { registerMemberCSVService.registerMembersFromCsv(adminId, file); }); - // 검증: 발생한 예외가 `MEMBER_NOT_FOUND`인지 확인 assertEquals(MemberErrorCode.MEMBER_NOT_FOUND.getCustomCode(), exception.getCode().getCustomCode()); - verifyNoInteractions(commandMemberPort); // 회원 저장 로직이 실행안됨 + verifyNoInteractions(commandMemberPort); // 저장 로직 실행 안됨 } /** @@ -88,45 +85,39 @@ void testRegisterMembersFromCsvThrowsWhenCsvParsingFails() { Long adminId = 1L; MultipartFile file = new MockMultipartFile("file", "members.csv", "text/csv", "dummy-content".getBytes()); - // ✅ Mock 객체 설정: CSV 파싱 과정에서 예외 발생하도록 설정 when(csvParseService.parseDataAndMapToMember(file)).thenThrow(new ApplicationException(MemberErrorCode.CSV_PARSING_ERROR)); - // 🔹 유스케이스 실행 및 예외 검증 ApplicationException exception = assertThrows(ApplicationException.class, () -> { registerMemberCSVService.registerMembersFromCsv(adminId, file); }); - // ✅ 검증: 발생한 예외가 `CSV_PARSING_ERROR`인지 확인 assertEquals(MemberErrorCode.CSV_PARSING_ERROR.getCustomCode(), exception.getCode().getCustomCode()); - verifyNoInteractions(commandMemberPort); // ❗ 회원 저장 로직이 실행되지 않아야 함 + verifyNoInteractions(commandMemberPort); // 저장 로직 실행 안됨 } /** * ❌ 회원 등록 실패 (MEMBER_REGISTRATION_FAILED) - * */ -// @Test -// @DisplayName("회원 등록 과정 중 실패 시 예외 발생 및 부분 저장 된다.") -// void testRegisterMembersFromCsvThrowsWhenSavingMemberFails() { -// Long adminId = 1L; -// MultipartFile file = new MockMultipartFile("file", "members.csv", "text/csv", "dummy-content".getBytes()); -// -// Member admin = Mockito.mock(Member.class); -// Member failingMember = Mockito.mock(Member.class); -// List parsedMembers = List.of(failingMember, Mockito.mock(Member.class)); -// -// // 특정 회원 등록 중 예외 발생 -// when(memberService.findActiveMember(adminId)).thenReturn(admin); -// when(csvParseService.parseDataAndMapToMember(file)).thenReturn(parsedMembers); -// doThrow(new ApplicationException(MemberErrorCode.MEMBER_REGISTRATION_FAILED)) -// .when(commandMemberPort).save(failingMember); -// -// // Usecase 실행 -// ApplicationException exception = assertThrows(ApplicationException.class, () -> { -// registerMemberCSVService.registerMembersFromCsv(adminId, file); -// }); -// -// assertEquals(MemberErrorCode.MEMBER_REGISTRATION_FAILED.getCustomCode(), exception.getCode().getCustomCode()); -// verify(commandMemberPort, times(1)).save(failingMember); // ❗ 실패한 회원만 저장 시도해야 함 -// } + @Test + @DisplayName("회원 등록 과정 중 실패 시 예외 발생 및 회원 저장이 중단된다.") + void testRegisterMembersFromCsvThrowsWhenSavingMemberFails() { + Long adminId = 1L; + MultipartFile file = new MockMultipartFile("file", "members.csv", "text/csv", "dummy-content".getBytes()); + + Member admin = Mockito.mock(Member.class); + Member failingMember = Mockito.mock(Member.class); + List parsedMembers = List.of(failingMember); + + when(memberService.findActiveMember(adminId)).thenReturn(admin); + when(csvParseService.parseDataAndMapToMember(file)).thenReturn(parsedMembers); + doThrow(new ApplicationException(MemberErrorCode.MEMBER_REGISTRATION_FAILED)) + .when(commandMemberPort).saveAll(parsedMembers); + + ApplicationException exception = assertThrows(ApplicationException.class, () -> { + registerMemberCSVService.registerMembersFromCsv(adminId, file); + }); + + assertEquals(MemberErrorCode.MEMBER_REGISTRATION_FAILED.getCustomCode(), exception.getCode().getCustomCode()); + verify(commandMemberPort).saveAll(parsedMembers); + } } From e1039c576e592c4f44c50409d41bc46674b64386 Mon Sep 17 00:00:00 2001 From: Sihun23 Date: Wed, 5 Feb 2025 14:53:52 +0900 Subject: [PATCH 3/3] CLAP-284 remove:test code --- .../admin/RegisterMemberCSVServiceTest.java | 123 ------------------ 1 file changed, 123 deletions(-) delete mode 100644 src/test/java/clap/server/application/service/admin/RegisterMemberCSVServiceTest.java diff --git a/src/test/java/clap/server/application/service/admin/RegisterMemberCSVServiceTest.java b/src/test/java/clap/server/application/service/admin/RegisterMemberCSVServiceTest.java deleted file mode 100644 index 165a3cbb..00000000 --- a/src/test/java/clap/server/application/service/admin/RegisterMemberCSVServiceTest.java +++ /dev/null @@ -1,123 +0,0 @@ -package clap.server.application.service.admin; - -import clap.server.application.port.inbound.domain.MemberService; -import clap.server.application.port.outbound.member.CommandMemberPort; -import clap.server.domain.model.member.Member; -import clap.server.exception.ApplicationException; -import clap.server.exception.code.MemberErrorCode; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.mockito.Mockito; -import org.springframework.mock.web.MockMultipartFile; -import org.springframework.web.multipart.MultipartFile; - -import java.util.List; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; - -class RegisterMemberCSVServiceTest { - - private RegisterMemberCSVService registerMemberCSVService; - private MemberService memberService; - private CommandMemberPort commandMemberPort; - private CsvParseService csvParseService; - - @BeforeEach - void setup() { - memberService = Mockito.mock(MemberService.class); - commandMemberPort = Mockito.mock(CommandMemberPort.class); - csvParseService = Mockito.mock(CsvParseService.class); - registerMemberCSVService = new RegisterMemberCSVService(memberService, commandMemberPort, csvParseService); - } - - /** - * ✅ 정상적인 회원 등록 테스트 - */ - @Test - @DisplayName("CSV 파일에서 회원 정보를 성공적으로 파싱하고 등록하는지 검증한다.") - void testRegisterMembersFromCsvSuccess() { - Long adminId = 1L; - MultipartFile file = new MockMultipartFile("file", "members.csv", "text/csv", "name,nickname,departmentId,departmentRole,email,role,isReviewer\nJohn,JohnDoe,1,Manager,john.doe@example.com,ROLE_USER,TRUE".getBytes()); - - Member admin = Mockito.mock(Member.class); - Member member1 = Mockito.mock(Member.class); - Member member2 = Mockito.mock(Member.class); - List parsedMembers = List.of(member1, member2); - - when(memberService.findActiveMember(adminId)).thenReturn(admin); - when(csvParseService.parseDataAndMapToMember(file)).thenReturn(parsedMembers); - - int addedCount = registerMemberCSVService.registerMembersFromCsv(adminId, file); - - assertEquals(2, addedCount); // 2명이 성공적으로 등록됨 - verify(commandMemberPort).saveAll(parsedMembers); // 모든 회원 저장 - verify(member1).register(admin); // 관리자와 연결 - verify(member2).register(admin); // 관리자와 연결 - } - - /** - * ❌ 관리자 찾기 실패 (MEMBER_NOT_FOUND) - */ - @Test - @DisplayName("관리자가 존재하지 않을 때 CSV 회원 등록 시 예외가 발생한다.") - void testRegisterMembersFromCsvThrowsWhenAdminNotFound() { - Long adminId = 99L; - MultipartFile file = new MockMultipartFile("file", "members.csv", "text/csv", "dummy-content".getBytes()); - - when(memberService.findActiveMember(adminId)).thenThrow(new ApplicationException(MemberErrorCode.MEMBER_NOT_FOUND)); - - ApplicationException exception = assertThrows(ApplicationException.class, () -> { - registerMemberCSVService.registerMembersFromCsv(adminId, file); - }); - - assertEquals(MemberErrorCode.MEMBER_NOT_FOUND.getCustomCode(), exception.getCode().getCustomCode()); - verifyNoInteractions(commandMemberPort); // 저장 로직 실행 안됨 - } - - /** - * ❌ CSV 파싱 실패 (CSV_PARSING_ERROR) - */ - @Test - @DisplayName("CSV 파싱 실패 시 예외 발생 및 회원 등록이 실패한다.") - void testRegisterMembersFromCsvThrowsWhenCsvParsingFails() { - Long adminId = 1L; - MultipartFile file = new MockMultipartFile("file", "members.csv", "text/csv", "dummy-content".getBytes()); - - when(csvParseService.parseDataAndMapToMember(file)).thenThrow(new ApplicationException(MemberErrorCode.CSV_PARSING_ERROR)); - - ApplicationException exception = assertThrows(ApplicationException.class, () -> { - registerMemberCSVService.registerMembersFromCsv(adminId, file); - }); - - assertEquals(MemberErrorCode.CSV_PARSING_ERROR.getCustomCode(), exception.getCode().getCustomCode()); - verifyNoInteractions(commandMemberPort); // 저장 로직 실행 안됨 - } - - /** - * ❌ 회원 등록 실패 (MEMBER_REGISTRATION_FAILED) - */ - @Test - @DisplayName("회원 등록 과정 중 실패 시 예외 발생 및 회원 저장이 중단된다.") - void testRegisterMembersFromCsvThrowsWhenSavingMemberFails() { - Long adminId = 1L; - MultipartFile file = new MockMultipartFile("file", "members.csv", "text/csv", "dummy-content".getBytes()); - - Member admin = Mockito.mock(Member.class); - Member failingMember = Mockito.mock(Member.class); - List parsedMembers = List.of(failingMember); - - when(memberService.findActiveMember(adminId)).thenReturn(admin); - when(csvParseService.parseDataAndMapToMember(file)).thenReturn(parsedMembers); - doThrow(new ApplicationException(MemberErrorCode.MEMBER_REGISTRATION_FAILED)) - .when(commandMemberPort).saveAll(parsedMembers); - - ApplicationException exception = assertThrows(ApplicationException.class, () -> { - registerMemberCSVService.registerMembersFromCsv(adminId, file); - }); - - assertEquals(MemberErrorCode.MEMBER_REGISTRATION_FAILED.getCustomCode(), exception.getCode().getCustomCode()); - verify(commandMemberPort).saveAll(parsedMembers); - } -}