From c590f55a3f3f869b5931ff14d156c5d26b24a8e0 Mon Sep 17 00:00:00 2001 From: hseong3243 Date: Mon, 29 Jan 2024 21:50:57 +0900 Subject: [PATCH 1/5] =?UTF-8?q?feat:=20=EB=A7=81=ED=81=AC=20=EB=B2=88?= =?UTF-8?q?=EB=93=A4=20=EC=83=9D=EC=84=B1=20=EC=84=9C=EB=B9=84=EC=8A=A4=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/linkbundle/LinkBundle.java | 19 +++++ .../service/LinkBundleRepository.java | 8 ++ .../linkbundle/service/LinkBundleService.java | 28 +++++++ .../response/CreateLinkBundleCommand.java | 5 ++ .../response/CreateLinkBundleResponse.java | 5 ++ .../repository/FakeLinkBundleRepository.java | 22 ++++++ .../service/LinkBundleServiceTest.java | 74 +++++++++++++++++++ 7 files changed, 161 insertions(+) create mode 100644 src/main/java/com/seong/shoutlink/domain/linkbundle/LinkBundle.java create mode 100644 src/main/java/com/seong/shoutlink/domain/linkbundle/service/LinkBundleRepository.java create mode 100644 src/main/java/com/seong/shoutlink/domain/linkbundle/service/LinkBundleService.java create mode 100644 src/main/java/com/seong/shoutlink/domain/linkbundle/service/response/CreateLinkBundleCommand.java create mode 100644 src/main/java/com/seong/shoutlink/domain/linkbundle/service/response/CreateLinkBundleResponse.java create mode 100644 src/test/java/com/seong/shoutlink/domain/linkbundle/repository/FakeLinkBundleRepository.java create mode 100644 src/test/java/com/seong/shoutlink/domain/linkbundle/service/LinkBundleServiceTest.java diff --git a/src/main/java/com/seong/shoutlink/domain/linkbundle/LinkBundle.java b/src/main/java/com/seong/shoutlink/domain/linkbundle/LinkBundle.java new file mode 100644 index 0000000..ea8e4d5 --- /dev/null +++ b/src/main/java/com/seong/shoutlink/domain/linkbundle/LinkBundle.java @@ -0,0 +1,19 @@ +package com.seong.shoutlink.domain.linkbundle; + +import com.seong.shoutlink.domain.member.Member; +import lombok.Getter; + +@Getter +public class LinkBundle { + + private Long linkBundleId; + private String description; + private boolean isDefault; + private Member member; + + public LinkBundle(String description, boolean isDefault, Member member) { + this.description = description; + this.isDefault = isDefault; + this.member = member; + } +} diff --git a/src/main/java/com/seong/shoutlink/domain/linkbundle/service/LinkBundleRepository.java b/src/main/java/com/seong/shoutlink/domain/linkbundle/service/LinkBundleRepository.java new file mode 100644 index 0000000..2961404 --- /dev/null +++ b/src/main/java/com/seong/shoutlink/domain/linkbundle/service/LinkBundleRepository.java @@ -0,0 +1,8 @@ +package com.seong.shoutlink.domain.linkbundle.service; + +import com.seong.shoutlink.domain.linkbundle.LinkBundle; + +public interface LinkBundleRepository { + + Long save(LinkBundle linkBundle); +} diff --git a/src/main/java/com/seong/shoutlink/domain/linkbundle/service/LinkBundleService.java b/src/main/java/com/seong/shoutlink/domain/linkbundle/service/LinkBundleService.java new file mode 100644 index 0000000..c830da8 --- /dev/null +++ b/src/main/java/com/seong/shoutlink/domain/linkbundle/service/LinkBundleService.java @@ -0,0 +1,28 @@ +package com.seong.shoutlink.domain.linkbundle.service; + +import com.seong.shoutlink.domain.exception.ErrorCode; +import com.seong.shoutlink.domain.exception.ShoutLinkException; +import com.seong.shoutlink.domain.linkbundle.LinkBundle; +import com.seong.shoutlink.domain.linkbundle.service.response.CreateLinkBundleCommand; +import com.seong.shoutlink.domain.linkbundle.service.response.CreateLinkBundleResponse; +import com.seong.shoutlink.domain.member.Member; +import com.seong.shoutlink.domain.member.service.MemberRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +public class LinkBundleService { + + private final MemberRepository memberRepository; + private final LinkBundleRepository linkBundleRepository; + + @Transactional + public CreateLinkBundleResponse createLinkBundle(CreateLinkBundleCommand command) { + Member member = memberRepository.findById(command.memberId()) + .orElseThrow(() -> new ShoutLinkException("존재하지 않는 사용자입니다.", ErrorCode.NOT_FOUND)); + LinkBundle linkBundle = new LinkBundle(command.description(), command.isDefault(), member); + return new CreateLinkBundleResponse(linkBundleRepository.save(linkBundle)); + } +} diff --git a/src/main/java/com/seong/shoutlink/domain/linkbundle/service/response/CreateLinkBundleCommand.java b/src/main/java/com/seong/shoutlink/domain/linkbundle/service/response/CreateLinkBundleCommand.java new file mode 100644 index 0000000..3d7ef6f --- /dev/null +++ b/src/main/java/com/seong/shoutlink/domain/linkbundle/service/response/CreateLinkBundleCommand.java @@ -0,0 +1,5 @@ +package com.seong.shoutlink.domain.linkbundle.service.response; + +public record CreateLinkBundleCommand(Long memberId, String description, boolean isDefault) { + +} diff --git a/src/main/java/com/seong/shoutlink/domain/linkbundle/service/response/CreateLinkBundleResponse.java b/src/main/java/com/seong/shoutlink/domain/linkbundle/service/response/CreateLinkBundleResponse.java new file mode 100644 index 0000000..a3551a3 --- /dev/null +++ b/src/main/java/com/seong/shoutlink/domain/linkbundle/service/response/CreateLinkBundleResponse.java @@ -0,0 +1,5 @@ +package com.seong.shoutlink.domain.linkbundle.service.response; + +public record CreateLinkBundleResponse(Long linkBundleId) { + +} diff --git a/src/test/java/com/seong/shoutlink/domain/linkbundle/repository/FakeLinkBundleRepository.java b/src/test/java/com/seong/shoutlink/domain/linkbundle/repository/FakeLinkBundleRepository.java new file mode 100644 index 0000000..afe49e0 --- /dev/null +++ b/src/test/java/com/seong/shoutlink/domain/linkbundle/repository/FakeLinkBundleRepository.java @@ -0,0 +1,22 @@ +package com.seong.shoutlink.domain.linkbundle.repository; + +import com.seong.shoutlink.domain.linkbundle.LinkBundle; +import com.seong.shoutlink.domain.linkbundle.service.LinkBundleRepository; +import java.util.HashMap; +import java.util.Map; + +public class FakeLinkBundleRepository implements LinkBundleRepository { + + private final Map memory = new HashMap<>(); + + @Override + public Long save(LinkBundle linkBundle) { + long nextId = getNextId(); + memory.put(nextId, linkBundle); + return nextId; + } + + private long getNextId() { + return memory.keySet().size() + 1; + } +} diff --git a/src/test/java/com/seong/shoutlink/domain/linkbundle/service/LinkBundleServiceTest.java b/src/test/java/com/seong/shoutlink/domain/linkbundle/service/LinkBundleServiceTest.java new file mode 100644 index 0000000..7c23a40 --- /dev/null +++ b/src/test/java/com/seong/shoutlink/domain/linkbundle/service/LinkBundleServiceTest.java @@ -0,0 +1,74 @@ +package com.seong.shoutlink.domain.linkbundle.service; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchException; + +import com.seong.shoutlink.domain.exception.ErrorCode; +import com.seong.shoutlink.domain.exception.ShoutLinkException; +import com.seong.shoutlink.domain.linkbundle.repository.FakeLinkBundleRepository; +import com.seong.shoutlink.domain.linkbundle.service.response.CreateLinkBundleCommand; +import com.seong.shoutlink.domain.linkbundle.service.response.CreateLinkBundleResponse; +import com.seong.shoutlink.domain.member.Member; +import com.seong.shoutlink.domain.member.repository.StubMemberRepository; +import com.seong.shoutlink.fixture.MemberFixture; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +class LinkBundleServiceTest { + + @Nested + @DisplayName("createLinkBundle 메서드 호출 시") + class CreateLinkBundleTest { + + private Member savedMember; + private LinkBundleService linkBundleService; + private StubMemberRepository memberRepository; + private FakeLinkBundleRepository linkBundleRepository; + + @BeforeEach + void setUp() { + savedMember = MemberFixture.member(); + memberRepository = new StubMemberRepository(savedMember); + linkBundleRepository = new FakeLinkBundleRepository(); + linkBundleService = new LinkBundleService(memberRepository, linkBundleRepository); + } + + @Test + @DisplayName("성공: 링크 번들 생성됨") + void createLinkBundle() { + //given + CreateLinkBundleCommand command = new CreateLinkBundleCommand( + savedMember.getMemberId(), + "간단한 설명", + true); + + //when + CreateLinkBundleResponse response = linkBundleService.createLinkBundle(command); + + //then + assertThat(response.linkBundleId()).isEqualTo(1); + } + + @Test + @DisplayName("예외(NotFound): 존재하지 않는 사용자") + void notFound_WhenMemberNotFound() { + //given + Long notFoundMember = savedMember.getMemberId() + 1; + CreateLinkBundleCommand command = new CreateLinkBundleCommand( + notFoundMember, + "간단한 설명", + true); + + //when + Exception exception = catchException(() -> linkBundleService.createLinkBundle(command)); + + //then + assertThat(exception) + .isInstanceOf(ShoutLinkException.class) + .extracting(e -> ((ShoutLinkException) e).getErrorCode()) + .isEqualTo(ErrorCode.NOT_FOUND); + } + } +} \ No newline at end of file From 604f102499c463cfededdecf66fbc15212d5c2ff Mon Sep 17 00:00:00 2001 From: hseong3243 Date: Mon, 29 Jan 2024 21:51:27 +0900 Subject: [PATCH 2/5] =?UTF-8?q?feat:=20=EB=A7=81=ED=81=AC=20=EB=B2=88?= =?UTF-8?q?=EB=93=A4=20=EC=83=9D=EC=84=B1=20=EC=98=81=EC=86=8D=EC=84=B1=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/LinkBundleEntity.java | 43 +++++++++++++++++++ .../repository/LinkBundleJpaRepository.java | 7 +++ .../repository/LinkBundleRepositoryImpl.java | 20 +++++++++ 3 files changed, 70 insertions(+) create mode 100644 src/main/java/com/seong/shoutlink/domain/linkbundle/repository/LinkBundleEntity.java create mode 100644 src/main/java/com/seong/shoutlink/domain/linkbundle/repository/LinkBundleJpaRepository.java create mode 100644 src/main/java/com/seong/shoutlink/domain/linkbundle/repository/LinkBundleRepositoryImpl.java diff --git a/src/main/java/com/seong/shoutlink/domain/linkbundle/repository/LinkBundleEntity.java b/src/main/java/com/seong/shoutlink/domain/linkbundle/repository/LinkBundleEntity.java new file mode 100644 index 0000000..3a7e3ec --- /dev/null +++ b/src/main/java/com/seong/shoutlink/domain/linkbundle/repository/LinkBundleEntity.java @@ -0,0 +1,43 @@ +package com.seong.shoutlink.domain.linkbundle.repository; + +import com.seong.shoutlink.domain.linkbundle.LinkBundle; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class LinkBundleEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long linkBundleId; + + private String description; + private boolean isDefault; + private Long memberId; + + private LinkBundleEntity( + Long linkBundleId, + String description, + boolean isDefault, + Long memberId) { + this.linkBundleId = linkBundleId; + this.description = description; + this.isDefault = isDefault; + this.memberId = memberId; + } + + public static LinkBundleEntity create(LinkBundle linkBundle) { + return new LinkBundleEntity( + linkBundle.getLinkBundleId(), + linkBundle.getDescription(), + linkBundle.isDefault(), + linkBundle.getMember().getMemberId()); + } +} diff --git a/src/main/java/com/seong/shoutlink/domain/linkbundle/repository/LinkBundleJpaRepository.java b/src/main/java/com/seong/shoutlink/domain/linkbundle/repository/LinkBundleJpaRepository.java new file mode 100644 index 0000000..b346769 --- /dev/null +++ b/src/main/java/com/seong/shoutlink/domain/linkbundle/repository/LinkBundleJpaRepository.java @@ -0,0 +1,7 @@ +package com.seong.shoutlink.domain.linkbundle.repository; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface LinkBundleJpaRepository extends JpaRepository { + +} diff --git a/src/main/java/com/seong/shoutlink/domain/linkbundle/repository/LinkBundleRepositoryImpl.java b/src/main/java/com/seong/shoutlink/domain/linkbundle/repository/LinkBundleRepositoryImpl.java new file mode 100644 index 0000000..c42d1fb --- /dev/null +++ b/src/main/java/com/seong/shoutlink/domain/linkbundle/repository/LinkBundleRepositoryImpl.java @@ -0,0 +1,20 @@ +package com.seong.shoutlink.domain.linkbundle.repository; + +import com.seong.shoutlink.domain.linkbundle.LinkBundle; +import com.seong.shoutlink.domain.linkbundle.service.LinkBundleRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Repository; + +@Repository +@RequiredArgsConstructor +public class LinkBundleRepositoryImpl implements LinkBundleRepository { + + private final LinkBundleJpaRepository linkBundleJpaRepository; + + @Override + public Long save(LinkBundle linkBundle) { + LinkBundleEntity linkBundleEntity = LinkBundleEntity.create(linkBundle); + linkBundleJpaRepository.save(linkBundleEntity); + return linkBundleEntity.getLinkBundleId(); + } +} From c944fedfd877d971ea639bbc4f6fb58cfd4c3cc1 Mon Sep 17 00:00:00 2001 From: hseong3243 Date: Mon, 29 Jan 2024 23:31:16 +0900 Subject: [PATCH 3/5] =?UTF-8?q?feat:=20=ED=9A=8C=EC=9B=90=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EC=8B=9C=20=ED=9A=8C=EC=9B=90=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=EB=B0=9C=ED=96=89=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/auth/service/AuthService.java | 13 +++++-- .../auth/service/event/CreateMemberEvent.java | 7 ++++ .../domain/auth/service/AuthServiceTest.java | 35 ++++++++++++++++--- 3 files changed, 48 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/seong/shoutlink/domain/auth/service/event/CreateMemberEvent.java diff --git a/src/main/java/com/seong/shoutlink/domain/auth/service/AuthService.java b/src/main/java/com/seong/shoutlink/domain/auth/service/AuthService.java index 6cfd0ff..f6d11c6 100644 --- a/src/main/java/com/seong/shoutlink/domain/auth/service/AuthService.java +++ b/src/main/java/com/seong/shoutlink/domain/auth/service/AuthService.java @@ -2,19 +2,22 @@ import com.seong.shoutlink.domain.auth.JwtProvider; import com.seong.shoutlink.domain.auth.PasswordEncoder; +import com.seong.shoutlink.domain.auth.service.event.CreateMemberEvent; import com.seong.shoutlink.domain.auth.service.request.CreateMemberCommand; import com.seong.shoutlink.domain.auth.service.request.LoginCommand; import com.seong.shoutlink.domain.auth.service.response.CreateMemberResponse; import com.seong.shoutlink.domain.auth.service.response.LoginResponse; import com.seong.shoutlink.domain.auth.service.response.TokenResponse; +import com.seong.shoutlink.domain.common.EventPublisher; +import com.seong.shoutlink.domain.exception.ErrorCode; +import com.seong.shoutlink.domain.exception.ShoutLinkException; import com.seong.shoutlink.domain.member.Member; import com.seong.shoutlink.domain.member.MemberRole; import com.seong.shoutlink.domain.member.service.MemberRepository; -import com.seong.shoutlink.domain.exception.ErrorCode; -import com.seong.shoutlink.domain.exception.ShoutLinkException; import java.util.regex.Pattern; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; @Service @RequiredArgsConstructor @@ -26,6 +29,7 @@ public class AuthService { private final MemberRepository memberRepository; private final PasswordEncoder passwordEncoder; private final JwtProvider jwtProvider; + private final EventPublisher eventPublisher; private void validatePassword(CreateMemberCommand command) { if(!PASSWORD_PATTEN.matcher(command.password()).matches()) { @@ -34,6 +38,7 @@ private void validatePassword(CreateMemberCommand command) { } } + @Transactional public CreateMemberResponse createMember(CreateMemberCommand command) { validatePassword(command); memberRepository.findByEmail(command.email()) @@ -49,7 +54,9 @@ public CreateMemberResponse createMember(CreateMemberCommand command) { passwordEncoder.encode(command.password()), command.nickname(), MemberRole.ROLE_USER); - return new CreateMemberResponse(memberRepository.save(member)); + Long memberId = memberRepository.save(member); + eventPublisher.publishEvent(new CreateMemberEvent(memberId)); + return new CreateMemberResponse(memberId); } public LoginResponse login(LoginCommand command) { diff --git a/src/main/java/com/seong/shoutlink/domain/auth/service/event/CreateMemberEvent.java b/src/main/java/com/seong/shoutlink/domain/auth/service/event/CreateMemberEvent.java new file mode 100644 index 0000000..ffbb7a8 --- /dev/null +++ b/src/main/java/com/seong/shoutlink/domain/auth/service/event/CreateMemberEvent.java @@ -0,0 +1,7 @@ +package com.seong.shoutlink.domain.auth.service.event; + +import com.seong.shoutlink.domain.common.Event; + +public record CreateMemberEvent(Long memberId) implements Event { + +} diff --git a/src/test/java/com/seong/shoutlink/domain/auth/service/AuthServiceTest.java b/src/test/java/com/seong/shoutlink/domain/auth/service/AuthServiceTest.java index c34f681..31d52c1 100644 --- a/src/test/java/com/seong/shoutlink/domain/auth/service/AuthServiceTest.java +++ b/src/test/java/com/seong/shoutlink/domain/auth/service/AuthServiceTest.java @@ -9,12 +9,13 @@ import com.seong.shoutlink.domain.auth.service.request.LoginCommand; import com.seong.shoutlink.domain.auth.service.response.CreateMemberResponse; import com.seong.shoutlink.domain.auth.service.response.LoginResponse; +import com.seong.shoutlink.domain.common.StubEventPublisher; +import com.seong.shoutlink.domain.exception.ErrorCode; +import com.seong.shoutlink.domain.exception.ShoutLinkException; import com.seong.shoutlink.domain.member.Member; import com.seong.shoutlink.domain.member.MemberRole; import com.seong.shoutlink.domain.member.repository.StubMemberRepository; import com.seong.shoutlink.global.auth.jwt.JJwtProvider; -import com.seong.shoutlink.domain.exception.ErrorCode; -import com.seong.shoutlink.domain.exception.ShoutLinkException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; @@ -37,6 +38,7 @@ class CreateMemberTest { Member savedMember; StubMemberRepository memberRepository; AuthService authService; + StubEventPublisher eventPublisher; @BeforeEach void setUp() { @@ -46,7 +48,12 @@ void setUp() { MemberRole memberRole = MemberRole.ROLE_USER; savedMember = new Member(email, password, nickname, memberRole); memberRepository = new StubMemberRepository(savedMember); - authService = new AuthService(memberRepository, passwordEncoder, jwtProvider); + eventPublisher = new StubEventPublisher(); + authService = new AuthService( + memberRepository, + passwordEncoder, + jwtProvider, + eventPublisher); } @ParameterizedTest @@ -121,6 +128,20 @@ void duplicateNickname_WhenNicknameIsDuplicate() { .extracting(e -> ((ShoutLinkException) e).getErrorCode()) .isEqualTo(ErrorCode.DUPLICATE_NICKNAME); } + + @Test + @DisplayName("성공: 회원 생성 이벤트 발행함") + void publishCreateMemberEvent() { + //given + CreateMemberCommand command + = new CreateMemberCommand("email@email.com", "asdf123!", "nickname"); + + //when + CreateMemberResponse response = authService.createMember(command); + + //then + assertThat(eventPublisher.getPublishEventCount()).isEqualTo(1); + } } @Nested @@ -131,6 +152,7 @@ class LoginTest { Member savedMember; StubMemberRepository memberRepository; AuthService authService; + StubEventPublisher eventPublisher; @BeforeEach void setUp() { @@ -141,7 +163,12 @@ void setUp() { MemberRole memberRole = MemberRole.ROLE_USER; savedMember = new Member(1L, email, password, nickname, memberRole); memberRepository = new StubMemberRepository(savedMember); - authService = new AuthService(memberRepository, passwordEncoder, jwtProvider); + eventPublisher = new StubEventPublisher(); + authService = new AuthService( + memberRepository, + passwordEncoder, + jwtProvider, + eventPublisher); } @Test From be43254bb77267b0be52b5e67fc824341cb85738 Mon Sep 17 00:00:00 2001 From: hseong3243 Date: Mon, 29 Jan 2024 23:32:16 +0900 Subject: [PATCH 4/5] =?UTF-8?q?feat:=20=ED=9A=8C=EC=9B=90=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=EC=88=98=EC=8B=A0=20?= =?UTF-8?q?=EC=8B=9C=20=EA=B8=B0=EB=B3=B8=20=EB=A7=81=ED=81=AC=20=EB=B2=88?= =?UTF-8?q?=EB=93=A4=20=EC=83=9D=EC=84=B1=20=EB=A1=9C=EC=A7=81=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../shoutlink/global/config/EventConfig.java | 7 +++ .../global/event/SpringEventListener.java | 26 +++++++++ .../global/event/SpringEventListenerTest.java | 54 +++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 src/main/java/com/seong/shoutlink/global/event/SpringEventListener.java create mode 100644 src/test/java/com/seong/shoutlink/global/event/SpringEventListenerTest.java diff --git a/src/main/java/com/seong/shoutlink/global/config/EventConfig.java b/src/main/java/com/seong/shoutlink/global/config/EventConfig.java index cb5f9dc..4684613 100644 --- a/src/main/java/com/seong/shoutlink/global/config/EventConfig.java +++ b/src/main/java/com/seong/shoutlink/global/config/EventConfig.java @@ -1,6 +1,8 @@ package com.seong.shoutlink.global.config; import com.seong.shoutlink.domain.common.EventPublisher; +import com.seong.shoutlink.domain.linkbundle.service.LinkBundleService; +import com.seong.shoutlink.global.event.SpringEventListener; import com.seong.shoutlink.global.event.SpringEventPublisher; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.annotation.Bean; @@ -13,4 +15,9 @@ public class EventConfig { public EventPublisher eventPublisher(ApplicationEventPublisher applicationEventPublisher) { return new SpringEventPublisher(applicationEventPublisher); } + + @Bean + public SpringEventListener springEventListener(LinkBundleService linkBundleService) { + return new SpringEventListener(linkBundleService); + } } diff --git a/src/main/java/com/seong/shoutlink/global/event/SpringEventListener.java b/src/main/java/com/seong/shoutlink/global/event/SpringEventListener.java new file mode 100644 index 0000000..e8fe60d --- /dev/null +++ b/src/main/java/com/seong/shoutlink/global/event/SpringEventListener.java @@ -0,0 +1,26 @@ +package com.seong.shoutlink.global.event; + +import com.seong.shoutlink.domain.auth.service.event.CreateMemberEvent; +import com.seong.shoutlink.domain.linkbundle.service.LinkBundleService; +import com.seong.shoutlink.domain.linkbundle.service.response.CreateLinkBundleCommand; +import lombok.RequiredArgsConstructor; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.transaction.event.TransactionPhase; +import org.springframework.transaction.event.TransactionalEventListener; + +@RequiredArgsConstructor +public class SpringEventListener { + + private static final String DEFAULT_LINK_BUNDLE = "기본"; + + private final LinkBundleService linkBundleService; + + @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) + @Transactional(propagation = Propagation.REQUIRES_NEW) + public void createDefaultLinkBundle(CreateMemberEvent event) { + CreateLinkBundleCommand command + = new CreateLinkBundleCommand(event.memberId(), DEFAULT_LINK_BUNDLE, true); + linkBundleService.createLinkBundle(command); + } +} diff --git a/src/test/java/com/seong/shoutlink/global/event/SpringEventListenerTest.java b/src/test/java/com/seong/shoutlink/global/event/SpringEventListenerTest.java new file mode 100644 index 0000000..eca9963 --- /dev/null +++ b/src/test/java/com/seong/shoutlink/global/event/SpringEventListenerTest.java @@ -0,0 +1,54 @@ +package com.seong.shoutlink.global.event; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.seong.shoutlink.domain.auth.service.AuthService; +import com.seong.shoutlink.domain.auth.service.request.CreateMemberCommand; +import com.seong.shoutlink.domain.linkbundle.repository.LinkBundleEntity; +import com.seong.shoutlink.domain.member.Member; +import com.seong.shoutlink.fixture.MemberFixture; +import jakarta.persistence.EntityManager; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.event.RecordApplicationEvents; + +@SpringBootTest +@RecordApplicationEvents +class SpringEventListenerTest { + + @Autowired + private AuthService authService; + + @Autowired + private EntityManager em; + + @Nested + @DisplayName("createMemberEvent 수신 시") + class CreateMemberEventTest { + + @Test + @DisplayName("성공: 기본 링크 번들 생성됨") + void createDefaultLinkBundle() { + //given + Member member = MemberFixture.member(); + CreateMemberCommand createMemberCommand = new CreateMemberCommand( + member.getEmail(), + member.getPassword(), + member.getNickname()); + + //when + authService.createMember(createMemberCommand); + + //then + LinkBundleEntity linkBundleEntity = em.createQuery( + "select lb from LinkBundleEntity lb where lb.memberId = :memberId", + LinkBundleEntity.class) + .setParameter("memberId", member.getMemberId()) + .getSingleResult(); + assertThat(linkBundleEntity.getDescription()).isEqualTo("기본"); + } + } +} \ No newline at end of file From 1fcff56cb6b4b3cb77e8f465a01638e15770fdc1 Mon Sep 17 00:00:00 2001 From: hseong3243 Date: Mon, 29 Jan 2024 23:36:42 +0900 Subject: [PATCH 5/5] =?UTF-8?q?style:=20=ED=8C=8C=EC=9D=BC=20=EB=81=9D?= =?UTF-8?q?=EC=97=90=20=EA=B0=9C=ED=96=89=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/linkbundle/service/LinkBundleServiceTest.java | 2 +- .../seong/shoutlink/global/event/SpringEventListenerTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/seong/shoutlink/domain/linkbundle/service/LinkBundleServiceTest.java b/src/test/java/com/seong/shoutlink/domain/linkbundle/service/LinkBundleServiceTest.java index 7c23a40..27dafa1 100644 --- a/src/test/java/com/seong/shoutlink/domain/linkbundle/service/LinkBundleServiceTest.java +++ b/src/test/java/com/seong/shoutlink/domain/linkbundle/service/LinkBundleServiceTest.java @@ -71,4 +71,4 @@ void notFound_WhenMemberNotFound() { .isEqualTo(ErrorCode.NOT_FOUND); } } -} \ No newline at end of file +} diff --git a/src/test/java/com/seong/shoutlink/global/event/SpringEventListenerTest.java b/src/test/java/com/seong/shoutlink/global/event/SpringEventListenerTest.java index eca9963..57e01ed 100644 --- a/src/test/java/com/seong/shoutlink/global/event/SpringEventListenerTest.java +++ b/src/test/java/com/seong/shoutlink/global/event/SpringEventListenerTest.java @@ -51,4 +51,4 @@ void createDefaultLinkBundle() { assertThat(linkBundleEntity.getDescription()).isEqualTo("기본"); } } -} \ No newline at end of file +}