Skip to content

Commit

Permalink
test: Added tests
Browse files Browse the repository at this point in the history
- added the Order, Voucher tests
- added the synchronisation test
- added application.yml for the test profile
  • Loading branch information
koreanMike513 committed Dec 29, 2024
1 parent 1fba7b5 commit 1191e69
Show file tree
Hide file tree
Showing 4 changed files with 202 additions and 0 deletions.
69 changes: 69 additions & 0 deletions src/test/java/com/f_lab/la_planete/domain/OrderTest.java
Original file line number Diff line number Diff line change
@@ -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));
}
}
58 changes: 58 additions & 0 deletions src/test/java/com/f_lab/la_planete/domain/VoucherTest.java
Original file line number Diff line number Diff line change
@@ -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);

}
}
7 changes: 7 additions & 0 deletions src/test/java/com/f_lab/la_planete/resources/application.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
spring:
profiles:
active: test

jpa:
hibernate:
ddl-auto: create-drop
Original file line number Diff line number Diff line change
@@ -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);
}
}

0 comments on commit 1191e69

Please sign in to comment.