From 1191e695ecfd000df3fc8a873ab6e9cd88e77b86 Mon Sep 17 00:00:00 2001 From: koreanMike513 Date: Sun, 29 Dec 2024 21:57:07 +0000 Subject: [PATCH] test: Added tests - added the Order, Voucher tests - added the synchronisation test - added application.yml for the test profile --- .../f_lab/la_planete/domain/OrderTest.java | 69 +++++++++++++++++++ .../f_lab/la_planete/domain/VoucherTest.java | 58 ++++++++++++++++ .../la_planete/resources/application.yml | 7 ++ .../OrderServiceSynchronisationTest.java | 68 ++++++++++++++++++ 4 files changed, 202 insertions(+) create mode 100644 src/test/java/com/f_lab/la_planete/domain/OrderTest.java create mode 100644 src/test/java/com/f_lab/la_planete/domain/VoucherTest.java create mode 100644 src/test/java/com/f_lab/la_planete/resources/application.yml create mode 100644 src/test/java/com/f_lab/la_planete/service/OrderServiceSynchronisationTest.java diff --git a/src/test/java/com/f_lab/la_planete/domain/OrderTest.java b/src/test/java/com/f_lab/la_planete/domain/OrderTest.java new file mode 100644 index 0000000..79ee4f1 --- /dev/null +++ b/src/test/java/com/f_lab/la_planete/domain/OrderTest.java @@ -0,0 +1,69 @@ +package com.f_lab.la_planete.domain; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.LocalDateTime; +import java.time.Month; + + +class OrderTest { + + Currency KRW = Currency.builder() + .currencyCode("KRW") + .currencySymbol("₩") + .roundingScale(0) + .roundingMode(RoundingMode.FLOOR) + .build(); + + Food food = Food.builder() + .price(BigDecimal.valueOf(10000)) + .currency(KRW) + .totalQuantity(1000) + .build(); + + Voucher voucher = Voucher.builder() + .discountRate(BigDecimal.valueOf(0.45)) + .expiryDate(LocalDateTime.of(3000, Month.DECEMBER, 12, 23, 59)) + .build(); + + @Test + @DisplayName("할인 쿠폰이 있는 경우에 calculateTotalCost() 메서드") + void test_totalCost_given_food_and_voucher_success() { + // given + BigDecimal totalCost = food.calculateCost(3); + Order order = Order.builder() + .food(food) + .totalCost(totalCost) + .quantity(3) + .voucher(voucher) + .build(); + + // when + BigDecimal calculatedTotalCost = order.calculateTotalCost(); + + // then + Assertions.assertThat(calculatedTotalCost).isEqualTo(BigDecimal.valueOf(16500)); + } + + @Test + @DisplayName("할인 쿠폰이 없는 경우에 calculateTotalCost() 메서드") + void test_totalCost_given_food_and_without_voucher_success() { + // given + BigDecimal totalCost = food.calculateCost(3); + Order order = Order.builder() + .food(food) + .totalCost(totalCost) + .quantity(3) + .build(); + + // when + BigDecimal calculatedTotalCost = order.calculateTotalCost(); + + // then + Assertions.assertThat(calculatedTotalCost).isEqualTo(BigDecimal.valueOf(30000)); + } +} \ No newline at end of file diff --git a/src/test/java/com/f_lab/la_planete/domain/VoucherTest.java b/src/test/java/com/f_lab/la_planete/domain/VoucherTest.java new file mode 100644 index 0000000..27fef8c --- /dev/null +++ b/src/test/java/com/f_lab/la_planete/domain/VoucherTest.java @@ -0,0 +1,58 @@ +package com.f_lab.la_planete.domain; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.math.BigDecimal; +import java.math.RoundingMode; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class VoucherTest { + Currency GBP = Currency.builder() + .currencyCode("GBP") + .currencySymbol("£") + .roundingScale(2) + .roundingMode(RoundingMode.FLOOR) + .build(); + + Currency KRW = Currency.builder() + .currencyCode("KRW") + .currencySymbol("₩") + .roundingScale(0) + .roundingMode(RoundingMode.FLOOR) + .build(); + + @Test + @DisplayName("0 ~ 100 사이의 값이 들어올 때 정상적으로 할인이 적용된 값을 return") + void test_voucher_discount_success() { + // given + Voucher voucher = new Voucher(); + voucher.setDiscountRate(BigDecimal.valueOf(0.25)); + + // when + BigDecimal afterDiscountsGBP1 = voucher.apply(BigDecimal.valueOf(100), GBP); + BigDecimal afterDiscountsGBP2 = voucher.apply(BigDecimal.valueOf(500.4), GBP); + BigDecimal afterDiscountsKRW3 = voucher.apply(BigDecimal.valueOf(100), KRW); + + // then + assertThat(afterDiscountsGBP1).isEqualTo(BigDecimal.valueOf(75.00).setScale(2)); + assertThat(afterDiscountsGBP2).isEqualTo(BigDecimal.valueOf(375.30).setScale(2)); + assertThat(afterDiscountsKRW3).isEqualTo(BigDecimal.valueOf(75)); + } + + @Test + @DisplayName("currency 값에 null 값이 들어갔을 경우에 예외를 던진다.") + void test_voucher_discount_failure() { + // given + Voucher voucher = new Voucher(); + voucher.setDiscountRate(BigDecimal.valueOf(0.25)); + + // when + assertThatThrownBy(() -> + voucher.apply(BigDecimal.valueOf(100), null) + ).isInstanceOf(IllegalStateException.class); + + } +} \ No newline at end of file diff --git a/src/test/java/com/f_lab/la_planete/resources/application.yml b/src/test/java/com/f_lab/la_planete/resources/application.yml new file mode 100644 index 0000000..9330456 --- /dev/null +++ b/src/test/java/com/f_lab/la_planete/resources/application.yml @@ -0,0 +1,7 @@ +spring: + profiles: + active: test + + jpa: + hibernate: + ddl-auto: create-drop \ No newline at end of file diff --git a/src/test/java/com/f_lab/la_planete/service/OrderServiceSynchronisationTest.java b/src/test/java/com/f_lab/la_planete/service/OrderServiceSynchronisationTest.java new file mode 100644 index 0000000..acd4b8e --- /dev/null +++ b/src/test/java/com/f_lab/la_planete/service/OrderServiceSynchronisationTest.java @@ -0,0 +1,68 @@ +package com.f_lab.la_planete.service; + +import com.f_lab.la_planete.domain.Food; +import com.f_lab.la_planete.dto.request.OrderCreateRequestDTO; +import com.f_lab.la_planete.repository.FoodRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + + +import java.math.BigDecimal; +import java.util.concurrent.*; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest +class OrderServiceSynchronisationTest { + + @Autowired + OrderService orderService; + + @Autowired + FoodRepository foodRepository; + + Food dummyFood = Food.builder() + .price(BigDecimal.valueOf(1000)) + .totalQuantity(1000) + .build(); + + OrderCreateRequestDTO request = OrderCreateRequestDTO.builder() + .foodId(1L) + .price(BigDecimal.valueOf(1000)) + .quantity(10) + .build(); + + @BeforeEach + void beforeEach() { + foodRepository.saveAndFlush(dummyFood); + } + + @Test + @DisplayName("동시성 테스트 100개의 요청이 동시에 왔을 때 데이터의 일관성이 유지") + void test_concurrency_thread_100_success() throws InterruptedException { + // given + int count = 100; + CountDownLatch countDownLatch = new CountDownLatch(count); + ExecutorService executorService = Executors.newFixedThreadPool(count); + + // when + for (int i = 0; i < count; i++) { + executorService.submit(() -> { + try { + orderService.createFoodOrder(request); + } finally { + countDownLatch.countDown(); + } + }); + } + + countDownLatch.await(); + + // then + Food food = foodRepository.findById(1L).orElseThrow(); + assertThat(food.getTotalQuantity()).isEqualTo(0L); + } +} \ No newline at end of file