diff --git a/src/main/java/com/prgrms/catchtable/common/notification/NotificationContent.java b/src/main/java/com/prgrms/catchtable/common/notification/NotificationContent.java index 54b616eb..63c028b8 100644 --- a/src/main/java/com/prgrms/catchtable/common/notification/NotificationContent.java +++ b/src/main/java/com/prgrms/catchtable/common/notification/NotificationContent.java @@ -1,20 +1,22 @@ package com.prgrms.catchtable.common.notification; +import java.util.function.Function; import lombok.Getter; import lombok.RequiredArgsConstructor; @RequiredArgsConstructor @Getter public enum NotificationContent { - RESERVATION_COMPLETED("예약이 완료되었습니다"), - RESERVATION_ONE_HOUR_LEFT("예약 시간 1시간 전입니다."), - RESERVATION_TIME_TO_ENTER("예약시간이 되었습니다"), - WAITING_REGISTER_COMPLETED("웨이팅 등록이 완료되었습니다"), - WAITING_RANK_THIRD("웨이팅 순서가 3번째가 되었습니다"), - WAITING_TIME_TO_ENTER("웨이팅이 끝났습니다. 입장 부탁드립니다."), - WAITING_CANCELLED_AUTOMATICALLY("웨이팅이 자동으로 취소되었습니다."); + RESERVATION_COMPLETED(time -> time.concat(" 시간의 예약이 완료 되었습니다.")), + RESERVATION_CANCELLED(time -> time.concat(" 시간의 예약이 취소 되었습니다")), + RESERVATION_ONE_HOUR_LEFT(time -> time.concat(" 시간 예약까지 한시간 남았습니다")), + RESERVATION_TIME_OUT(time -> "예약 시간이 되었습니다. 입장해주세요."); - private final String message; + private final Function expression; + + public String getMessage(String time) { + return expression.apply(time); + } } diff --git a/src/main/java/com/prgrms/catchtable/common/notification/NotificationEvent.java b/src/main/java/com/prgrms/catchtable/common/notification/NotificationEvent.java index eba2c6e1..e8254a04 100644 --- a/src/main/java/com/prgrms/catchtable/common/notification/NotificationEvent.java +++ b/src/main/java/com/prgrms/catchtable/common/notification/NotificationEvent.java @@ -2,9 +2,11 @@ import static org.springframework.transaction.event.TransactionPhase.AFTER_COMMIT; +import com.prgrms.catchtable.member.domain.Member; import com.prgrms.catchtable.notification.dto.request.SendMessageToMemberRequest; import com.prgrms.catchtable.notification.dto.request.SendMessageToOwnerRequest; import com.prgrms.catchtable.notification.service.NotificationService; +import com.prgrms.catchtable.owner.domain.Owner; import lombok.RequiredArgsConstructor; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; @@ -19,12 +21,18 @@ public class NotificationEvent { @Async @TransactionalEventListener(phase = AFTER_COMMIT) // 호출한쪽의 트랜잭션이 커밋 된 후 이벤트 발생 public void sendMessage(SendMessageToMemberRequest request) { - notificationService.sendMessageAndSave(request.member(), request.content()); + Member member = request.member(); + if (member.isNotification_activated()) { + notificationService.sendMessageAndSave(member, request.content()); + } } @Async @TransactionalEventListener(phase = AFTER_COMMIT) // 호출한쪽의 트랜잭션이 커밋 된 후 이벤트 발생 public void sendMessage(SendMessageToOwnerRequest request) { - notificationService.sendMessageAndSave(request.owner(), request.content()); + Owner owner = request.owner(); + if (owner.isNotification_activated()) { + notificationService.sendMessageAndSave(request.owner(), request.content()); + } } } diff --git a/src/main/java/com/prgrms/catchtable/notification/dto/request/SendMessageToMemberRequest.java b/src/main/java/com/prgrms/catchtable/notification/dto/request/SendMessageToMemberRequest.java index 4e9fb6f7..53fc5072 100644 --- a/src/main/java/com/prgrms/catchtable/notification/dto/request/SendMessageToMemberRequest.java +++ b/src/main/java/com/prgrms/catchtable/notification/dto/request/SendMessageToMemberRequest.java @@ -1,11 +1,10 @@ package com.prgrms.catchtable.notification.dto.request; -import com.prgrms.catchtable.common.notification.NotificationContent; import com.prgrms.catchtable.member.domain.Member; import lombok.Builder; @Builder public record SendMessageToMemberRequest(Member member, - NotificationContent content) { + String content) { } diff --git a/src/main/java/com/prgrms/catchtable/notification/dto/request/SendMessageToOwnerRequest.java b/src/main/java/com/prgrms/catchtable/notification/dto/request/SendMessageToOwnerRequest.java index ae80ddef..e6e0e42e 100644 --- a/src/main/java/com/prgrms/catchtable/notification/dto/request/SendMessageToOwnerRequest.java +++ b/src/main/java/com/prgrms/catchtable/notification/dto/request/SendMessageToOwnerRequest.java @@ -1,11 +1,10 @@ package com.prgrms.catchtable.notification.dto.request; -import com.prgrms.catchtable.common.notification.NotificationContent; import com.prgrms.catchtable.owner.domain.Owner; import lombok.Builder; @Builder public record SendMessageToOwnerRequest(Owner owner, - NotificationContent content) { + String content) { } diff --git a/src/main/java/com/prgrms/catchtable/notification/service/NotificationService.java b/src/main/java/com/prgrms/catchtable/notification/service/NotificationService.java index 5e298cd1..2d5a8bb3 100644 --- a/src/main/java/com/prgrms/catchtable/notification/service/NotificationService.java +++ b/src/main/java/com/prgrms/catchtable/notification/service/NotificationService.java @@ -5,7 +5,6 @@ import static org.springframework.http.HttpMethod.POST; import com.prgrms.catchtable.common.exception.custom.BadRequestCustomException; -import com.prgrms.catchtable.common.notification.NotificationContent; import com.prgrms.catchtable.member.domain.Member; import com.prgrms.catchtable.member.repository.MemberRepository; import com.prgrms.catchtable.notification.domain.NotificationMember; @@ -38,11 +37,11 @@ public class NotificationService { private final OwnerRepository ownerRepository; // 추후 삭제 예정 private JSONObject jsonObject; - public void sendMessageAndSave(Member member, NotificationContent content) { + public void sendMessageAndSave(Member member, String content) { String url = "https://slack.com/api/chat.postMessage"; // slack 메세지를 보내도록 요청하는 Slack API String email = member.getEmail(); - String message = content.getMessage(); + String message = content; String slackId = getSlackIdByEmail(email); // 이메일을 통해 사용자의 슬랙 고유 ID 추출 requestToSendMessage(slackId, message); // 알림 요청 보내는 함수 호출 @@ -56,11 +55,11 @@ public void sendMessageAndSave(Member member, NotificationContent content) { } - public void sendMessageAndSave(Owner owner, NotificationContent content) { + public void sendMessageAndSave(Owner owner, String content) { String url = "https://slack.com/api/chat.postMessage"; // slack 메세지를 보내도록 요청하는 Slack API String email = owner.getEmail(); - String message = content.getMessage(); + String message = content; String slackId = getSlackIdByEmail(email); requestToSendMessage(slackId, message); diff --git a/src/main/java/com/prgrms/catchtable/owner/domain/Owner.java b/src/main/java/com/prgrms/catchtable/owner/domain/Owner.java index 8e748ae3..d5a06b1a 100644 --- a/src/main/java/com/prgrms/catchtable/owner/domain/Owner.java +++ b/src/main/java/com/prgrms/catchtable/owner/domain/Owner.java @@ -61,6 +61,9 @@ public class Owner extends BaseEntity implements UserDetails { @Column(name = "date_birth") private LocalDate dateBirth; + @Column(name = "notification_activated") + private boolean notification_activated; + @OneToOne(fetch = LAZY) @JoinColumn(name = "shop_id", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) private Shop shop; @@ -75,6 +78,7 @@ public Owner(String name, String email, String password, String phoneNumber, Gen this.gender = gender; this.dateBirth = dateBirth; this.role = Role.OWNER; + this.notification_activated = true; } @Override diff --git a/src/main/java/com/prgrms/catchtable/owner/repository/OwnerRepository.java b/src/main/java/com/prgrms/catchtable/owner/repository/OwnerRepository.java index 5e783c0e..26443879 100644 --- a/src/main/java/com/prgrms/catchtable/owner/repository/OwnerRepository.java +++ b/src/main/java/com/prgrms/catchtable/owner/repository/OwnerRepository.java @@ -1,6 +1,7 @@ package com.prgrms.catchtable.owner.repository; import com.prgrms.catchtable.owner.domain.Owner; +import com.prgrms.catchtable.shop.domain.Shop; import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; @@ -10,4 +11,6 @@ public interface OwnerRepository extends JpaRepository { Optional findOwnerByEmail(String email); + Optional findOwnerByShop(Shop shop); + } diff --git a/src/main/java/com/prgrms/catchtable/reservation/controller/MemberReservationController.java b/src/main/java/com/prgrms/catchtable/reservation/controller/MemberReservationController.java index 3cbaa1a9..de49cee6 100644 --- a/src/main/java/com/prgrms/catchtable/reservation/controller/MemberReservationController.java +++ b/src/main/java/com/prgrms/catchtable/reservation/controller/MemberReservationController.java @@ -52,8 +52,9 @@ public ResponseEntity modifyReservation( @DeleteMapping("/{reservationId}") public ResponseEntity cancelReservation( + @LogIn Member member, @PathVariable("reservationId") Long reservationId) { - return ResponseEntity.ok(memberReservationService.cancelReservation(reservationId)); + return ResponseEntity.ok(memberReservationService.cancelReservation(member, reservationId)); } @GetMapping diff --git a/src/main/java/com/prgrms/catchtable/reservation/service/MemberReservationService.java b/src/main/java/com/prgrms/catchtable/reservation/service/MemberReservationService.java index ee07abdc..f27b601e 100644 --- a/src/main/java/com/prgrms/catchtable/reservation/service/MemberReservationService.java +++ b/src/main/java/com/prgrms/catchtable/reservation/service/MemberReservationService.java @@ -2,8 +2,11 @@ import static com.prgrms.catchtable.common.exception.ErrorCode.ALREADY_OCCUPIED_RESERVATION_TIME; import static com.prgrms.catchtable.common.exception.ErrorCode.ALREADY_PREOCCUPIED_RESERVATION_TIME; +import static com.prgrms.catchtable.common.exception.ErrorCode.NOT_EXIST_OWNER; import static com.prgrms.catchtable.common.exception.ErrorCode.NOT_EXIST_RESERVATION; import static com.prgrms.catchtable.common.exception.ErrorCode.NOT_EXIST_TIME; +import static com.prgrms.catchtable.common.notification.NotificationContent.RESERVATION_CANCELLED; +import static com.prgrms.catchtable.common.notification.NotificationContent.RESERVATION_COMPLETED; import static com.prgrms.catchtable.reservation.domain.ReservationStatus.CANCELLED; import static com.prgrms.catchtable.reservation.domain.ReservationStatus.COMPLETED; import static com.prgrms.catchtable.reservation.dto.mapper.ReservationMapper.toCancelReservationResponse; @@ -13,7 +16,12 @@ import com.prgrms.catchtable.common.exception.custom.BadRequestCustomException; import com.prgrms.catchtable.common.exception.custom.NotFoundCustomException; +import com.prgrms.catchtable.common.notification.NotificationContent; import com.prgrms.catchtable.member.domain.Member; +import com.prgrms.catchtable.notification.dto.request.SendMessageToMemberRequest; +import com.prgrms.catchtable.notification.dto.request.SendMessageToOwnerRequest; +import com.prgrms.catchtable.owner.domain.Owner; +import com.prgrms.catchtable.owner.repository.OwnerRepository; import com.prgrms.catchtable.reservation.domain.Reservation; import com.prgrms.catchtable.reservation.domain.ReservationTime; import com.prgrms.catchtable.reservation.dto.mapper.ReservationMapper; @@ -29,6 +37,7 @@ import com.prgrms.catchtable.shop.domain.Shop; import java.util.List; import lombok.RequiredArgsConstructor; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -40,6 +49,8 @@ public class MemberReservationService { private final ReservationRepository reservationRepository; private final ReservationAsync reservationAsync; private final ReservationLockRepository reservationLockRepository; + private final OwnerRepository ownerRepository; + private final ApplicationEventPublisher publisher; @Transactional public CreateReservationResponse preOccupyReservation(Member member, @@ -52,7 +63,8 @@ public CreateReservationResponse preOccupyReservation(Member member, Thread.currentThread().interrupt(); } } - ReservationTime reservationTime = reservationTimeRepository.findById(reservationTimeId) + ReservationTime reservationTime = reservationTimeRepository.findByIdWithShop( + reservationTimeId) .orElseThrow(() -> { reservationLockRepository.unlock(reservationTimeId); return new NotFoundCustomException(NOT_EXIST_TIME); @@ -91,6 +103,10 @@ public CreateReservationResponse registerReservation(Member member, .member(member) .build(); Reservation savedReservation = reservationRepository.save(reservation); + + sendMessageToMemberAndOwner(member, reservationTime, + RESERVATION_COMPLETED); //점주와 회원에게 알림 발송 + return toCreateReservationResponse(savedReservation); } @@ -129,7 +145,7 @@ public ModifyReservationResponse modifyReservation(Long reservavtionId, } @Transactional - public CancelReservationResponse cancelReservation(Long reservationId) { + public CancelReservationResponse cancelReservation(Member member, Long reservationId) { Reservation reservation = reservationRepository.findByIdWithReservationTimeAndShop( reservationId) .orElseThrow(() -> new NotFoundCustomException(NOT_EXIST_RESERVATION)); @@ -140,9 +156,30 @@ public CancelReservationResponse cancelReservation(Long reservationId) { reservationTime.setOccupiedFalse(); + sendMessageToMemberAndOwner(member, reservationTime, RESERVATION_CANCELLED); + return toCancelReservationResponse(reservation); } + private void sendMessageToMemberAndOwner(Member member, ReservationTime reservationTime, + NotificationContent content) { + + Owner owner = ownerRepository.findOwnerByShop(reservationTime.getShop()) + .orElseThrow(() -> new NotFoundCustomException(NOT_EXIST_OWNER)); + + SendMessageToMemberRequest sendMessageToMember = new SendMessageToMemberRequest( + member, + content.getMessage(reservationTime.getTime().toString()) + ); // 회원에게 보낼 해당 시간대의 예약 완료 알림 생성 + + SendMessageToOwnerRequest sendMessageToOwner = new SendMessageToOwnerRequest(owner, + content.getMessage( + reservationTime.getTime().toString())); // 해당 시간의 예약 취소 메세지 dto 생성 + + publisher.publishEvent(sendMessageToMember); + publisher.publishEvent(sendMessageToOwner); // 취소한 예약의 매장 점주에게 예약 취소 알림 발송 + } + private void validateIsPreOccupied(ReservationTime reservationTime) { if (reservationTime.isPreOccupied()) { reservationLockRepository.unlock(reservationTime.getId()); diff --git a/src/test/java/com/prgrms/catchtable/owner/repository/OwnerRepositoryTest.java b/src/test/java/com/prgrms/catchtable/owner/repository/OwnerRepositoryTest.java new file mode 100644 index 00000000..6aae1a1f --- /dev/null +++ b/src/test/java/com/prgrms/catchtable/owner/repository/OwnerRepositoryTest.java @@ -0,0 +1,40 @@ +package com.prgrms.catchtable.owner.repository; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace.NONE; + +import com.prgrms.catchtable.owner.domain.Owner; +import com.prgrms.catchtable.owner.fixture.OwnerFixture; +import com.prgrms.catchtable.shop.domain.Shop; +import com.prgrms.catchtable.shop.fixture.ShopFixture; +import com.prgrms.catchtable.shop.repository.ShopRepository; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; + +@DataJpaTest +@AutoConfigureTestDatabase(replace = NONE) +class OwnerRepositoryTest { + + @Autowired + private OwnerRepository ownerRepository; + @Autowired + private ShopRepository shopRepository; + + @Test + @DisplayName("매장을 통해 점주를 찾을 수 있다") + void findByShop() { + Shop shop = ShopFixture.shop(); + Shop savedShop = shopRepository.save(shop); + + Owner owner = OwnerFixture.getOwner("injun", "injun2480"); + owner.insertShop(savedShop); + Owner savedOwner = ownerRepository.save(owner); + + Owner findOwner = ownerRepository.findOwnerByShop(savedShop).orElseThrow(); + + assertThat(findOwner).isEqualTo(savedOwner); + } +} \ No newline at end of file diff --git a/src/test/java/com/prgrms/catchtable/reservation/controller/MemberReservationControllerTest.java b/src/test/java/com/prgrms/catchtable/reservation/controller/MemberReservationControllerTest.java index e9f0e0a2..a4f288f2 100644 --- a/src/test/java/com/prgrms/catchtable/reservation/controller/MemberReservationControllerTest.java +++ b/src/test/java/com/prgrms/catchtable/reservation/controller/MemberReservationControllerTest.java @@ -18,6 +18,9 @@ import com.prgrms.catchtable.member.MemberFixture; import com.prgrms.catchtable.member.domain.Member; import com.prgrms.catchtable.member.repository.MemberRepository; +import com.prgrms.catchtable.owner.domain.Owner; +import com.prgrms.catchtable.owner.fixture.OwnerFixture; +import com.prgrms.catchtable.owner.repository.OwnerRepository; import com.prgrms.catchtable.reservation.domain.Reservation; import com.prgrms.catchtable.reservation.domain.ReservationTime; import com.prgrms.catchtable.reservation.dto.request.CreateReservationRequest; @@ -28,6 +31,7 @@ import com.prgrms.catchtable.shop.domain.Shop; import com.prgrms.catchtable.shop.repository.ShopRepository; import java.util.List; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; @@ -47,6 +51,8 @@ class MemberReservationControllerTest extends BaseIntegrationTest { private ReservationRepository reservationRepository; @Autowired private MemberRepository memberRepository; + @Autowired + private OwnerRepository ownerRepository; private Member member = MemberFixture.member("dlswns661035@gmail.com"); @BeforeEach @@ -54,6 +60,9 @@ void setUp() { Shop shop = ShopData.getShop(); Shop savedShop = shopRepository.save(shop); + Owner owner = OwnerFixture.getOwner("injun", "injun2480"); + owner.insertShop(savedShop); + ownerRepository.save(owner); Member savedMember = memberRepository.save(member); @@ -66,6 +75,11 @@ void setUp() { httpHeaders.add("RefreshToken", token.getRefreshToken()); } + @AfterEach + void tearDown() { + shopRepository.deleteAll(); + } + @Test @DisplayName("예약 선점 api 호출에 성공한다.") void preOccupyReservation() throws Exception { @@ -193,6 +207,7 @@ void cancelReservation() throws Exception { Reservation savedReservation = reservationRepository.save(reservation); mockMvc.perform(delete("/reservations/{reservationId}", savedReservation.getId()) + .headers(httpHeaders) .contentType(APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$.status").value(CANCELLED.toString())); diff --git a/src/test/java/com/prgrms/catchtable/reservation/service/MemberReservationServiceTest.java b/src/test/java/com/prgrms/catchtable/reservation/service/MemberReservationServiceTest.java index cf3ead87..438fe518 100644 --- a/src/test/java/com/prgrms/catchtable/reservation/service/MemberReservationServiceTest.java +++ b/src/test/java/com/prgrms/catchtable/reservation/service/MemberReservationServiceTest.java @@ -15,6 +15,9 @@ import com.prgrms.catchtable.common.exception.custom.NotFoundCustomException; import com.prgrms.catchtable.member.MemberFixture; import com.prgrms.catchtable.member.domain.Member; +import com.prgrms.catchtable.owner.domain.Owner; +import com.prgrms.catchtable.owner.fixture.OwnerFixture; +import com.prgrms.catchtable.owner.repository.OwnerRepository; import com.prgrms.catchtable.reservation.domain.Reservation; import com.prgrms.catchtable.reservation.domain.ReservationTime; import com.prgrms.catchtable.reservation.dto.request.CreateReservationRequest; @@ -36,6 +39,7 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.test.util.ReflectionTestUtils; @ExtendWith(MockitoExtension.class) @@ -49,6 +53,10 @@ class MemberReservationServiceTest { private ReservationAsync reservationAsync; @Mock private ReservationTimeRepository reservationTimeRepository; + @Mock + private OwnerRepository ownerRepository; + @Mock + private ApplicationEventPublisher publisher; @InjectMocks private MemberReservationService memberReservationService; private final String email = "dlswns661035@gmail.com"; @@ -63,7 +71,8 @@ void validateReservation() { CreateReservationRequest request = ReservationFixture.getCreateReservationRequestWithId( reservationTime.getId()); - when(reservationTimeRepository.findById(1L)).thenReturn(Optional.of(reservationTime)); + when(reservationTimeRepository.findByIdWithShop(1L)).thenReturn( + Optional.of(reservationTime)); when(reservationLockRepository.lock(1L)).thenReturn(TRUE); when(reservationLockRepository.unlock(1L)).thenReturn(TRUE); doNothing().when(reservationAsync).setPreOcuppied(reservationTime); @@ -91,7 +100,8 @@ void alreadyPreOccupied() { CreateReservationRequest request = ReservationFixture.getCreateReservationRequestWithId( reservationTime.getId()); - when(reservationTimeRepository.findById(1L)).thenReturn(Optional.of(reservationTime)); + when(reservationTimeRepository.findByIdWithShop(1L)).thenReturn( + Optional.of(reservationTime)); when(reservationLockRepository.lock(1L)).thenReturn(TRUE); //when @@ -106,6 +116,7 @@ void alreadyPreOccupied() { void registerReservation() { Member member = MemberFixture.member(email); ReservationTime reservationTime = ReservationFixture.getReservationTimePreOccupied(); + Owner owner = OwnerFixture.getOwner("dlswns661035@gmail.com", "injun2480"); CreateReservationRequest request = ReservationFixture.getCreateReservationRequest(); Reservation reservation = Reservation.builder() .status(COMPLETED) @@ -117,6 +128,8 @@ void registerReservation() { when(reservationTimeRepository.findByIdWithShop(any(Long.class))).thenReturn( Optional.of(reservationTime)); when(reservationRepository.save(any(Reservation.class))).thenReturn(reservation); + when(ownerRepository.findOwnerByShop(any(Shop.class))).thenReturn(Optional.of(owner)); +// doNothing().when(publisher.publishEvent(any(Object.class))); CreateReservationResponse response = memberReservationService.registerReservation(member, request); @@ -261,16 +274,19 @@ void modifyReservationOccupied() { @DisplayName("예약을 취소할 수 있다") void cancelReservation() { //given + Member member = MemberFixture.member("dlswns661035@gmail.com"); ReservationTime reservationTime = ReservationFixture.getReservationTimeOccupied(); ModifyReservationRequest request = ReservationFixture.getModifyReservationRequest(1L); Reservation reservation = ReservationFixture.getReservation(reservationTime); ReflectionTestUtils.setField(reservation, "id", 1L); + Owner owner = OwnerFixture.getOwner("dlswns661035@gmail.com", "injun2480"); when(reservationRepository.findByIdWithReservationTimeAndShop(1L)).thenReturn( Optional.of(reservation)); - + when(ownerRepository.findOwnerByShop(any(Shop.class))).thenReturn(Optional.of(owner)); //when CancelReservationResponse response = memberReservationService.cancelReservation( + member, reservation.getId()); //then @@ -285,11 +301,12 @@ void cancelReservation() { @Test @DisplayName("존재하지 않는 예약에 대한 삭제 요청 시 예외가 발생한다") void cancelReservationNotExist() { + Member member = MemberFixture.member("asd@gmail.com"); when(reservationRepository.findByIdWithReservationTimeAndShop(1L)).thenReturn( Optional.empty()); assertThrows(NotFoundCustomException.class, - () -> memberReservationService.cancelReservation(1L)); + () -> memberReservationService.cancelReservation(member, 1L)); } } \ No newline at end of file