diff --git a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/GiftCouponByMessageService.kt b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/GiftCouponByMessageService.kt new file mode 100644 index 0000000..d4eb806 --- /dev/null +++ b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/GiftCouponByMessageService.kt @@ -0,0 +1,61 @@ +package com.example.estdelivery.coupon.application + +import com.example.estdelivery.coupon.application.port.`in`.GiftCouponByMessageUseCase +import com.example.estdelivery.coupon.application.port.out.CreateGiftCouponMessageStatePort +import com.example.estdelivery.coupon.application.port.out.LoadMemberStatePort +import com.example.estdelivery.coupon.application.port.out.UpdateMemberStatePort +import com.example.estdelivery.coupon.application.port.out.ValidateGiftCouponCodeStatePort +import com.example.estdelivery.coupon.application.utils.TransactionArea +import com.example.estdelivery.coupon.domain.coupon.Coupon +import com.example.estdelivery.coupon.domain.coupon.GiftCouponCode +import com.example.estdelivery.coupon.domain.coupon.GiftMessage +import com.example.estdelivery.coupon.domain.member.Member + +class GiftCouponByMessageService( + loadMemberStatePort: LoadMemberStatePort, + createGiftCouponMessageStatePort: CreateGiftCouponMessageStatePort, + updateMemberStatePort: UpdateMemberStatePort, + validateGiftCouponCodeStatePort: ValidateGiftCouponCodeStatePort, + private val transactionArea: TransactionArea, + private val findMember: (Long) -> Member = { loadMemberStatePort.findMember(it) }, + private val createGiftMessage: (Member, Coupon, String, GiftCouponCode) -> GiftMessage = { sender, coupon, message, code -> + createGiftCouponMessageStatePort.create(sender, coupon, message, code) + }, + private val validateCouponCode: (GiftCouponCode) -> Boolean = { validateGiftCouponCodeStatePort.validate(it) }, + private val updateMembersCoupon: (Member) -> Unit = { updateMemberStatePort.updateMembersCoupon(it) } +) : GiftCouponByMessageUseCase { + /** + * 선물 메시지를 통해 쿠폰을 선물한다. + * + * 1. 보낼 사람의 정보를 조회한다. + * 2. 보낼 쿠폰의 정보를 조회한다. + * 3. 보낼 사람의 쿠폰북에서 쿠폰을 삭제한다. + * 4. 등록할 쿠폰 코드를 검증한다. + * 5. 선물 메시지를 생성한다. + * + * @param memberId 선물하는 회원 식별자 + * @param couponId 선물할 쿠폰 식별자 + * @param giftMessage 선물 메시지 + */ + override fun sendGiftAvailableCoupon(memberId: Long, couponId: Long, giftMessage: String): GiftMessage { + return transactionArea.run { + val sender = findMember(memberId) + val coupon = sender.showMyCouponBook().find { it.id == couponId } + if (coupon == null) { + throw IllegalArgumentException("쿠폰이 존재하지 않습니다.") + } + val couponCode: GiftCouponCode = getGiftCouponCode() + sender.useCoupon(coupon) + updateMembersCoupon(sender) + createGiftMessage(sender, coupon, giftMessage, couponCode) + } + } + + private fun getGiftCouponCode(): GiftCouponCode { + lateinit var couponCode: GiftCouponCode + do { + couponCode = GiftCouponCode.create() + } while (!validateCouponCode(couponCode)) + return couponCode + } +} diff --git a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/ServiceBeanManager.kt b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/ServiceBeanManager.kt index 368a444..8c15b5b 100644 --- a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/ServiceBeanManager.kt +++ b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/ServiceBeanManager.kt @@ -1,12 +1,33 @@ package com.example.estdelivery.coupon.application +import com.example.estdelivery.coupon.application.port.`in`.FindAvailableGiftCouponUseCase +import com.example.estdelivery.coupon.application.port.`in`.GiftCouponByMessageUseCase +import com.example.estdelivery.coupon.application.port.out.CreateGiftCouponMessageStatePort import com.example.estdelivery.coupon.application.port.out.LoadMemberStatePort +import com.example.estdelivery.coupon.application.port.out.UpdateMemberStatePort +import com.example.estdelivery.coupon.application.port.out.ValidateGiftCouponCodeStatePort +import com.example.estdelivery.coupon.application.utils.TransactionArea import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration @Configuration class ServiceBeanManager { @Bean - fun findAvailableGiftCouponService(loadMemberStatePort: LoadMemberStatePort) = + fun findAvailableGiftCouponUseCase(loadMemberStatePort: LoadMemberStatePort): FindAvailableGiftCouponUseCase = FindAvailableGiftCouponService(loadMemberStatePort) + + @Bean + fun giftCouponByMessageUseCase( + transactionArea: TransactionArea, + loadMemberStatePort: LoadMemberStatePort, + createGiftCouponMessageStatePort: CreateGiftCouponMessageStatePort, + validateGiftCouponCodeStatePort: ValidateGiftCouponCodeStatePort, + updateMemberStatePort: UpdateMemberStatePort, + ): GiftCouponByMessageUseCase = GiftCouponByMessageService( + loadMemberStatePort, + createGiftCouponMessageStatePort, + updateMemberStatePort, + validateGiftCouponCodeStatePort, + transactionArea, + ) } diff --git a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/in/GiftCouponByMessageUseCase.kt b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/in/GiftCouponByMessageUseCase.kt new file mode 100644 index 0000000..6c5a6fe --- /dev/null +++ b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/in/GiftCouponByMessageUseCase.kt @@ -0,0 +1,7 @@ +package com.example.estdelivery.coupon.application.port.`in` + +import com.example.estdelivery.coupon.domain.coupon.GiftMessage + +interface GiftCouponByMessageUseCase { + fun sendGiftAvailableCoupon(memberId: Long, couponId: Long, giftMessage: String): GiftMessage +} diff --git a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/in/web/GiftCouponMessageController.kt b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/in/web/GiftCouponMessageController.kt index aa9a72c..9cc5bb9 100644 --- a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/in/web/GiftCouponMessageController.kt +++ b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/in/web/GiftCouponMessageController.kt @@ -1,19 +1,26 @@ package com.example.estdelivery.coupon.application.port.`in`.web import com.example.estdelivery.coupon.application.port.`in`.FindAvailableGiftCouponUseCase +import com.example.estdelivery.coupon.application.port.`in`.GiftCouponByMessageUseCase import com.example.estdelivery.coupon.application.port.`in`.web.dto.GiftCouponResponse import com.example.estdelivery.coupon.application.port.`in`.web.dto.GiftCouponResponses +import com.example.estdelivery.coupon.application.port.`in`.web.dto.GiftMessageResponse import com.example.estdelivery.coupon.domain.coupon.Coupon.FixDiscountCoupon import com.example.estdelivery.coupon.domain.coupon.Coupon.RateDiscountCoupon +import java.net.URL import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PathVariable +import org.springframework.web.bind.annotation.PostMapping import org.springframework.web.bind.annotation.RequestHeader import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RequestParam import org.springframework.web.bind.annotation.RestController @RestController @RequestMapping("/gift-coupons") class GiftCouponMessageController( private val findAvailableGiftCouponUseCase: FindAvailableGiftCouponUseCase, + private val giftCouponByMessageUseCase: GiftCouponByMessageUseCase, ) { @GetMapping fun findAvailableGiftCoupons(@RequestHeader(value = "Member-ID") memberId: Long): GiftCouponResponses = @@ -29,4 +36,22 @@ class GiftCouponMessageController( }.let { GiftCouponResponses(it) } + + @PostMapping("/send/{couponId}") + fun sendGiftAvailableCoupon( + @RequestHeader(value = "Member-ID") memberId: Long, + @RequestParam message: String, + @PathVariable couponId: Long, + ): GiftMessageResponse = + giftCouponByMessageUseCase.sendGiftAvailableCoupon( + memberId, + couponId, + message, + ).let { + GiftMessageResponse( + senderName = it.sender.name, + description = it.giftMessage, + enrollHref = URL("http", "localhost", 8080, "/gift-coupons/enroll/${it.giftCouponCode.code}") + ) + } } diff --git a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/in/web/dto/GiftMessageResponse.kt b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/in/web/dto/GiftMessageResponse.kt new file mode 100644 index 0000000..c6ad5c8 --- /dev/null +++ b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/in/web/dto/GiftMessageResponse.kt @@ -0,0 +1,9 @@ +package com.example.estdelivery.coupon.application.port.`in`.web.dto + +import java.net.URL + +data class GiftMessageResponse( + val senderName: String, + val description: String, + val enrollHref: URL, +) diff --git a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/CreateGiftCouponMessageStatePort.kt b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/CreateGiftCouponMessageStatePort.kt new file mode 100644 index 0000000..89eee5d --- /dev/null +++ b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/CreateGiftCouponMessageStatePort.kt @@ -0,0 +1,10 @@ +package com.example.estdelivery.coupon.application.port.out + +import com.example.estdelivery.coupon.domain.coupon.Coupon +import com.example.estdelivery.coupon.domain.coupon.GiftCouponCode +import com.example.estdelivery.coupon.domain.coupon.GiftMessage +import com.example.estdelivery.coupon.domain.member.Member + +interface CreateGiftCouponMessageStatePort { + fun create(sender: Member, coupon: Coupon, message: String, giftCouponCode: GiftCouponCode): GiftMessage +} diff --git a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/ValidateGiftCouponCodeStatePort.kt b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/ValidateGiftCouponCodeStatePort.kt new file mode 100644 index 0000000..c4ded8e --- /dev/null +++ b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/ValidateGiftCouponCodeStatePort.kt @@ -0,0 +1,7 @@ +package com.example.estdelivery.coupon.application.port.out + +import com.example.estdelivery.coupon.domain.coupon.GiftCouponCode + +interface ValidateGiftCouponCodeStatePort { + fun validate(giftCouponCode: GiftCouponCode): Boolean +} \ No newline at end of file diff --git a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/GiftCouponMessageAdapter.kt b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/GiftCouponMessageAdapter.kt new file mode 100644 index 0000000..5e142e1 --- /dev/null +++ b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/GiftCouponMessageAdapter.kt @@ -0,0 +1,39 @@ +package com.example.estdelivery.coupon.application.port.out.adapter.persistence + +import com.example.estdelivery.coupon.application.port.out.CreateGiftCouponMessageStatePort +import com.example.estdelivery.coupon.application.port.out.ValidateGiftCouponCodeStatePort +import com.example.estdelivery.coupon.application.port.out.adapter.persistence.entity.GiftMessageEntity +import com.example.estdelivery.coupon.application.port.out.adapter.persistence.mapper.fromCoupon +import com.example.estdelivery.coupon.application.port.out.adapter.persistence.repository.GiftMessageRepository +import com.example.estdelivery.coupon.domain.coupon.Coupon +import com.example.estdelivery.coupon.domain.coupon.GiftCoupon +import com.example.estdelivery.coupon.domain.coupon.GiftCouponCode +import com.example.estdelivery.coupon.domain.coupon.GiftMessage +import com.example.estdelivery.coupon.domain.member.Member +import org.springframework.stereotype.Component + +@Component +class GiftCouponMessageAdapter( + private val giftMessageRepository: GiftMessageRepository, +) : CreateGiftCouponMessageStatePort, ValidateGiftCouponCodeStatePort { + override fun create(sender: Member, coupon: Coupon, message: String, giftCouponCode: GiftCouponCode): GiftMessage { + val giftMessageEntity = giftMessageRepository.save( + GiftMessageEntity( + sender = sender.id, + coupon = fromCoupon(coupon), + message = message, + enrollCode = giftCouponCode.code + ) + ) + return GiftMessage( + sender = sender, + giftMessage = giftMessageEntity.message, + giftCouponCode = GiftCouponCode(giftMessageEntity.enrollCode), + giftCoupon = GiftCoupon(coupon) + ) + } + + override fun validate(giftCouponCode: GiftCouponCode): Boolean { + return giftMessageRepository.existsByEnrollCode(giftCouponCode.code) + } +} diff --git a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/entity/GiftMessageEntity.kt b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/entity/GiftMessageEntity.kt new file mode 100644 index 0000000..d292050 --- /dev/null +++ b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/entity/GiftMessageEntity.kt @@ -0,0 +1,41 @@ +package com.example.estdelivery.coupon.application.port.out.adapter.persistence.entity + +import jakarta.persistence.Column +import jakarta.persistence.Entity +import jakarta.persistence.GeneratedValue +import jakarta.persistence.GenerationType +import jakarta.persistence.Id +import jakarta.persistence.JoinColumn +import jakarta.persistence.OneToOne +import jakarta.persistence.Table +import java.time.LocalDate + +@Entity +@Table(name = "gift_message") +class GiftMessageEntity( + val message: String, + @Column(name = "sender_id") + val sender: Long, + val enrollCode: String, + @OneToOne + @JoinColumn(name = "coupon_id") + val coupon: CouponEntity, + val enrollDate: LocalDate = LocalDate.now(), + val isUsed: Boolean = false, + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + val id: Long? = null, +) { + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is GiftMessageEntity) return false + + if (id != other.id) return false + + return true + } + + override fun hashCode(): Int { + return id?.hashCode() ?: 0 + } +} diff --git a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/repository/CouponRepository.kt b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/repository/CouponRepository.kt index f36b57c..cc33044 100644 --- a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/repository/CouponRepository.kt +++ b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/repository/CouponRepository.kt @@ -3,5 +3,4 @@ package com.example.estdelivery.coupon.application.port.out.adapter.persistence. import com.example.estdelivery.coupon.application.port.out.adapter.persistence.entity.CouponEntity import org.springframework.data.jpa.repository.JpaRepository -interface CouponRepository : - JpaRepository +interface CouponRepository : JpaRepository diff --git a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/repository/GiftMessageRepository.kt b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/repository/GiftMessageRepository.kt new file mode 100644 index 0000000..0952908 --- /dev/null +++ b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/repository/GiftMessageRepository.kt @@ -0,0 +1,8 @@ +package com.example.estdelivery.coupon.application.port.out.adapter.persistence.repository + +import com.example.estdelivery.coupon.application.port.out.adapter.persistence.entity.GiftMessageEntity +import org.springframework.data.jpa.repository.JpaRepository + +interface GiftMessageRepository : JpaRepository { + fun existsByEnrollCode(enrollCode: String): Boolean +} diff --git a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/repository/ShopRepository.kt b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/repository/ShopRepository.kt index 2c0616e..c3732a3 100644 --- a/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/repository/ShopRepository.kt +++ b/coupon/src/main/kotlin/com/example/estdelivery/coupon/application/port/out/adapter/persistence/repository/ShopRepository.kt @@ -3,5 +3,4 @@ package com.example.estdelivery.coupon.application.port.out.adapter.persistence. import com.example.estdelivery.coupon.application.port.out.adapter.persistence.entity.ShopEntity import org.springframework.data.jpa.repository.JpaRepository -interface ShopRepository : - JpaRepository +interface ShopRepository : JpaRepository diff --git a/coupon/src/main/kotlin/com/example/estdelivery/coupon/domain/coupon/GiftCouponCode.kt b/coupon/src/main/kotlin/com/example/estdelivery/coupon/domain/coupon/GiftCouponCode.kt new file mode 100644 index 0000000..19ebcf5 --- /dev/null +++ b/coupon/src/main/kotlin/com/example/estdelivery/coupon/domain/coupon/GiftCouponCode.kt @@ -0,0 +1,17 @@ +package com.example.estdelivery.coupon.domain.coupon + +import java.util.UUID + +data class GiftCouponCode( + val code: String, +) { + init { + require(code.isNotBlank()) { "쿠폰 선물 코드는 비어있을 수 없습니다." } + } + + companion object { + fun create(): GiftCouponCode { + return GiftCouponCode(UUID.randomUUID().toString().replace("-", "").substring(0..9)) + } + } +} diff --git a/coupon/src/main/kotlin/com/example/estdelivery/coupon/domain/coupon/GiftMessage.kt b/coupon/src/main/kotlin/com/example/estdelivery/coupon/domain/coupon/GiftMessage.kt new file mode 100644 index 0000000..db8318f --- /dev/null +++ b/coupon/src/main/kotlin/com/example/estdelivery/coupon/domain/coupon/GiftMessage.kt @@ -0,0 +1,10 @@ +package com.example.estdelivery.coupon.domain.coupon + +import com.example.estdelivery.coupon.domain.member.Member + +data class GiftMessage( + val sender: Member, + val giftMessage: String, + val giftCouponCode: GiftCouponCode, + val giftCoupon: GiftCoupon +) diff --git a/coupon/src/test/kotlin/com/example/estdelivery/coupon/application/GiftCouponByMessageServiceTest.kt b/coupon/src/test/kotlin/com/example/estdelivery/coupon/application/GiftCouponByMessageServiceTest.kt new file mode 100644 index 0000000..4d008cc --- /dev/null +++ b/coupon/src/test/kotlin/com/example/estdelivery/coupon/application/GiftCouponByMessageServiceTest.kt @@ -0,0 +1,66 @@ +package com.example.estdelivery.coupon.application + +import com.example.estdelivery.coupon.application.port.out.CreateGiftCouponMessageStatePort +import com.example.estdelivery.coupon.application.port.out.LoadMemberStatePort +import com.example.estdelivery.coupon.application.port.out.UpdateMemberStatePort +import com.example.estdelivery.coupon.application.port.out.ValidateGiftCouponCodeStatePort +import com.example.estdelivery.coupon.application.utils.TransactionArea +import com.example.estdelivery.coupon.domain.coupon.GiftCoupon +import com.example.estdelivery.coupon.domain.coupon.GiftCouponCode +import com.example.estdelivery.coupon.domain.coupon.GiftMessage +import com.example.estdelivery.coupon.domain.fixture.나눠준_비율_할인_쿠폰 +import com.example.estdelivery.coupon.domain.fixture.일건창 +import com.example.estdelivery.coupon.domain.member.Member +import io.kotest.core.spec.style.FreeSpec +import io.kotest.matchers.shouldBe +import io.mockk.every +import io.mockk.mockk +import io.mockk.slot + +class GiftCouponByMessageServiceTest : FreeSpec({ + val loadMemberStatePort = mockk() + val createGiftCouponMessageStatePort = mockk() + val updateMemberStatePort = mockk() + val validateGiftCouponCodeStatePort = mockk() + + lateinit var giftCouponByMessageService: GiftCouponByMessageService + beforeTest { + giftCouponByMessageService = GiftCouponByMessageService( + loadMemberStatePort, + createGiftCouponMessageStatePort, + updateMemberStatePort, + validateGiftCouponCodeStatePort, + TransactionArea() + ) + } + + "쿠폰 선물하기 위한 메시지를 전달받는다." { + // given + val 선물할_쿠폰 = 나눠준_비율_할인_쿠폰 + val 일건창 = 일건창().apply { + receiveCoupon(선물할_쿠폰) + } + val 변경된_회원_정보 = slot() + val 선물_메시지 = "선물 메시지" + val 쿠폰_코드 = GiftCouponCode.create() + + // when + every { loadMemberStatePort.findMember(일건창.id) } returns 일건창 + every { createGiftCouponMessageStatePort.create(일건창, 선물할_쿠폰, 선물_메시지, any()) } returns GiftMessage( + 일건창, + 선물_메시지, + 쿠폰_코드, + GiftCoupon(선물할_쿠폰) + ) + every { validateGiftCouponCodeStatePort.validate(any()) } returns true + every { updateMemberStatePort.updateMembersCoupon(capture(변경된_회원_정보)) } returns Unit + + val giftAvailableCoupon = + giftCouponByMessageService.sendGiftAvailableCoupon(일건창.id, 선물할_쿠폰.id!!, 선물_메시지) + + // then + 변경된_회원_정보.captured.showMyCouponBook().find { it.id == 선물할_쿠폰.id } shouldBe null + giftAvailableCoupon.sender shouldBe 일건창 + giftAvailableCoupon.giftCouponCode shouldBe 쿠폰_코드 + } +}) diff --git a/coupon/src/test/kotlin/com/example/estdelivery/coupon/application/port/in/web/GiftCouponMessageControllerTest.kt b/coupon/src/test/kotlin/com/example/estdelivery/coupon/application/port/in/web/GiftCouponMessageControllerTest.kt index 3fd4b46..3effe01 100644 --- a/coupon/src/test/kotlin/com/example/estdelivery/coupon/application/port/in/web/GiftCouponMessageControllerTest.kt +++ b/coupon/src/test/kotlin/com/example/estdelivery/coupon/application/port/in/web/GiftCouponMessageControllerTest.kt @@ -1,8 +1,12 @@ package com.example.estdelivery.coupon.application.port.`in`.web import com.example.estdelivery.coupon.application.port.`in`.FindAvailableGiftCouponUseCase +import com.example.estdelivery.coupon.application.port.`in`.GiftCouponByMessageUseCase import com.example.estdelivery.coupon.domain.coupon.GiftCoupon +import com.example.estdelivery.coupon.domain.coupon.GiftCouponCode +import com.example.estdelivery.coupon.domain.coupon.GiftMessage import com.example.estdelivery.coupon.domain.fixture.나눠준_비율_할인_쿠폰 +import com.example.estdelivery.coupon.domain.fixture.일건창 import com.ninjasquad.springmockk.MockkBean import io.mockk.every import org.junit.jupiter.api.Test @@ -11,6 +15,7 @@ import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMock import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest import org.springframework.test.web.servlet.MockMvc import org.springframework.test.web.servlet.get +import org.springframework.test.web.servlet.post private const val MEMBER_ID = "Member-ID" @@ -20,6 +25,9 @@ class GiftCouponMessageControllerTest { @MockkBean lateinit var findAvailableGiftCouponUseCase: FindAvailableGiftCouponUseCase + @MockkBean + lateinit var giftCouponByMessageUseCase: GiftCouponByMessageUseCase + @Autowired lateinit var mockMvc: MockMvc @@ -44,4 +52,37 @@ class GiftCouponMessageControllerTest { } } } + + @Test + fun `쿠폰 선물할 메시지를 전달받는다`() { + // given + val 일건창 = 일건창() + val 선물할_쿠폰 = GiftCoupon(나눠준_비율_할인_쿠폰) + + // when + val messageDescription = "선물 메시지" + val giftCode = "A1B2C3D4" + + every { + giftCouponByMessageUseCase.sendGiftAvailableCoupon(일건창.id, 선물할_쿠폰.coupon.id!!, messageDescription) + } returns GiftMessage( + sender = 일건창, + giftMessage = messageDescription, + giftCoupon = 선물할_쿠폰, + giftCouponCode = GiftCouponCode(giftCode) + ) + + // then + mockMvc.post("/gift-coupons/send/${선물할_쿠폰.coupon.id}") { + header(MEMBER_ID, 일건창.id) + param("message", messageDescription) + }.andExpect { + status { isOk() } + content { + jsonPath("$.enrollHref") { value("http://localhost:8080/gift-coupons/enroll/$giftCode") } + jsonPath("$.senderName") { value(일건창.name) } + jsonPath("$.description") { value(messageDescription) } + } + } + } } diff --git a/coupon/src/test/kotlin/com/example/estdelivery/coupon/domain/coupon/GiftCouponCodeTest.kt b/coupon/src/test/kotlin/com/example/estdelivery/coupon/domain/coupon/GiftCouponCodeTest.kt new file mode 100644 index 0000000..005bd54 --- /dev/null +++ b/coupon/src/test/kotlin/com/example/estdelivery/coupon/domain/coupon/GiftCouponCodeTest.kt @@ -0,0 +1,15 @@ +package com.example.estdelivery.coupon.domain.coupon + +import io.kotest.assertions.throwables.shouldThrow +import io.kotest.core.spec.style.FreeSpec +import io.kotest.matchers.shouldBe + +class GiftCouponCodeTest : FreeSpec({ + "쿠폰 선물 코드는 비어있을 수 없다." { + val code = "" + val exception = shouldThrow { + GiftCouponCode(code) + } + exception.message shouldBe "쿠폰 선물 코드는 비어있을 수 없습니다." + } +})