From 6493bb4a18d2bc12cf0d93d4d1d04945d5292213 Mon Sep 17 00:00:00 2001 From: k2works Date: Fri, 27 Dec 2024 10:39:44 +0900 Subject: [PATCH] refactor:Testcontainers Consolidate test container setup for repository tests Merged the PostgreSQL test container configuration into existing repository test classes, removing the redundant ProductRepositoryContainerTest file. This change streamlines the test setup, ensures consistency, and avoids duplicate configurations across repository tests. #13 --- .../department/DepartmentRepositoryTest.java | 23 +++++- .../employee/EmployeeRepositoryTest.java | 37 ++++++++- .../ProductCategoryRepositoryTest.java | 21 +++++ .../ProductRepositoryContainerTest.java | 77 ------------------- .../master/product/ProductRepositoryTest.java | 56 ++++++++++++++ 5 files changed, 135 insertions(+), 79 deletions(-) delete mode 100644 app/backend/api/src/test/java/com/example/sms/service/master/product/ProductRepositoryContainerTest.java diff --git a/app/backend/api/src/test/java/com/example/sms/service/master/department/DepartmentRepositoryTest.java b/app/backend/api/src/test/java/com/example/sms/service/master/department/DepartmentRepositoryTest.java index e58fab63..a401680e 100644 --- a/app/backend/api/src/test/java/com/example/sms/service/master/department/DepartmentRepositoryTest.java +++ b/app/backend/api/src/test/java/com/example/sms/service/master/department/DepartmentRepositoryTest.java @@ -8,14 +8,35 @@ 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.ActiveProfiles; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.utility.DockerImageName; import java.time.LocalDateTime; import static org.junit.jupiter.api.Assertions.assertEquals; @SpringBootTest +@Testcontainers +@ActiveProfiles("container") @DisplayName("部門レポジトリ") -public class DepartmentRepositoryTest { +class DepartmentRepositoryTest { + @Container + private static final PostgreSQLContainer postgres = + new PostgreSQLContainer<>(DockerImageName.parse("postgres:15")) + .withUsername("root") + .withPassword("password") + .withDatabaseName("postgres"); + + @DynamicPropertySource + static void setup(DynamicPropertyRegistry registry) { + registry.add("spring.datasource.url", postgres::getJdbcUrl); + } + @Autowired private DepartmentRepository repository; diff --git a/app/backend/api/src/test/java/com/example/sms/service/master/employee/EmployeeRepositoryTest.java b/app/backend/api/src/test/java/com/example/sms/service/master/employee/EmployeeRepositoryTest.java index 29595619..9352a2e9 100644 --- a/app/backend/api/src/test/java/com/example/sms/service/master/employee/EmployeeRepositoryTest.java +++ b/app/backend/api/src/test/java/com/example/sms/service/master/employee/EmployeeRepositoryTest.java @@ -1,23 +1,49 @@ package com.example.sms.service.master.employee; import com.example.sms.TestDataFactoryImpl; +import com.example.sms.domain.model.master.department.Department; import com.example.sms.domain.model.master.employee.Employee; +import com.example.sms.service.master.department.DepartmentRepository; 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 org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.utility.DockerImageName; import java.time.LocalDateTime; import static org.junit.jupiter.api.Assertions.assertEquals; @SpringBootTest +@Testcontainers +@ActiveProfiles("container") @DisplayName("社員レポジトリ") -public class EmployeeRepositoryTest { +class EmployeeRepositoryTest { + @Container + private static final PostgreSQLContainer postgres = + new PostgreSQLContainer<>(DockerImageName.parse("postgres:15")) + .withUsername("root") + .withPassword("password") + .withDatabaseName("postgres"); + + @DynamicPropertySource + static void setup(DynamicPropertyRegistry registry) { + registry.add("spring.datasource.url", postgres::getJdbcUrl); + } + @Autowired private EmployeeRepository repository; + @Autowired + private DepartmentRepository departmentRepository; + @BeforeEach void setUp() { repository.deleteAll(); @@ -27,6 +53,10 @@ private Employee getEmployee() { return TestDataFactoryImpl.employee("EMP999", "10000", LocalDateTime.of(2021, 1, 1, 0, 0)); } + private Department getDepartment() { + return TestDataFactoryImpl.department("10000", LocalDateTime.of(2021, 1, 1, 0, 0), "部署名"); + } + @Test @DisplayName("社員一覧を取得できる") void shouldRetrieveAllEmployees() { @@ -41,7 +71,9 @@ void shouldRetrieveAllEmployees() { @DisplayName("社員を登録できる") void shouldRegisterEmployee() { Employee employee = getEmployee(); + Department department = getDepartment(); + departmentRepository.save(department); repository.save(employee); Employee actual = repository.findById(employee.getEmpCode()).get(); @@ -61,6 +93,9 @@ void shouldRegisterEmployee() { @DisplayName("社員を更新できる") void shouldUpdateEmployee() { Employee employee = getEmployee(); + Department department = getDepartment(); + + departmentRepository.save(department); repository.save(employee); employee = repository.findById(employee.getEmpCode()).get(); diff --git a/app/backend/api/src/test/java/com/example/sms/service/master/product/ProductCategoryRepositoryTest.java b/app/backend/api/src/test/java/com/example/sms/service/master/product/ProductCategoryRepositoryTest.java index a58228cf..9805da20 100644 --- a/app/backend/api/src/test/java/com/example/sms/service/master/product/ProductCategoryRepositoryTest.java +++ b/app/backend/api/src/test/java/com/example/sms/service/master/product/ProductCategoryRepositoryTest.java @@ -11,6 +11,13 @@ 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.ActiveProfiles; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.utility.DockerImageName; import java.util.List; import java.util.stream.IntStream; @@ -18,8 +25,22 @@ import static org.junit.Assert.assertEquals; @SpringBootTest +@Testcontainers +@ActiveProfiles("container") @DisplayName("商品分類レポジトリ") public class ProductCategoryRepositoryTest { + @Container + private static final PostgreSQLContainer postgres = + new PostgreSQLContainer<>(DockerImageName.parse("postgres:15")) + .withUsername("root") + .withPassword("password") + .withDatabaseName("postgres"); + + @DynamicPropertySource + static void setup(DynamicPropertyRegistry registry) { + registry.add("spring.datasource.url", postgres::getJdbcUrl); + } + @Autowired private ProductCategoryRepository repository; @Autowired diff --git a/app/backend/api/src/test/java/com/example/sms/service/master/product/ProductRepositoryContainerTest.java b/app/backend/api/src/test/java/com/example/sms/service/master/product/ProductRepositoryContainerTest.java deleted file mode 100644 index bb2ba868..00000000 --- a/app/backend/api/src/test/java/com/example/sms/service/master/product/ProductRepositoryContainerTest.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.example.sms.service.master.product; - -import com.example.sms.TestDataFactoryImpl; -import com.example.sms.domain.model.master.product.Product; -import com.example.sms.domain.type.product.*; -import org.junit.jupiter.api.DisplayName; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.dao.OptimisticLockingFailureException; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.DynamicPropertyRegistry; -import org.springframework.test.context.DynamicPropertySource; -import org.testcontainers.containers.PostgreSQLContainer; -import org.testcontainers.junit.jupiter.Container; -import org.testcontainers.junit.jupiter.Testcontainers; -import org.testcontainers.utility.DockerImageName; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertThrows; - - -@Testcontainers -@SpringBootTest -@ActiveProfiles("container") -public class ProductRepositoryContainerTest { - @Container - private static final PostgreSQLContainer postgres = - new PostgreSQLContainer<>(DockerImageName.parse("postgres:15")) - .withUsername("root") - .withPassword("password") - .withDatabaseName("postgres"); - - @Autowired - ProductRepository repository; - - @DynamicPropertySource - static void setup(DynamicPropertyRegistry registry) { - registry.add("spring.datasource.url", postgres::getJdbcUrl); - } - - private Product getProduct(String productCode) { - return TestDataFactoryImpl.product(productCode, "商品正式名", "商品略称", "商品名カナ", ProductType.その他, 1000, 2000, 3000, TaxType.外税, "00000000", MiscellaneousType.適用外, StockManagementTargetType.対象, StockAllocationType.引当済, "00000000", 5); - } - - @Test - @DisplayName("楽観ロックが正常に動作すること") - void testOptimisticLockingWithThreads() throws InterruptedException { - // Productを新規作成して保存 - Product product1 = getProduct("99999999"); - repository.save(product1); - - // 同じIDのProductをもう一度データベースから取得 - Product product2 = repository.findById("99999999").orElseThrow(); - - // スレッド1でproduct1を更新 - Thread thread1 = new Thread(() -> { - Product updatedProduct1 = getProduct("99999999"); - repository.save(updatedProduct1); - }); - - // スレッド2でproduct2を更新し、例外を確認 - Thread thread2 = new Thread(() -> { - Product updatedProduct2 = getProduct("99999999"); - assertThrows(OptimisticLockingFailureException.class, () -> { - repository.save(updatedProduct2); - }); - }); - - // スレッドを開始 - thread1.start(); - thread2.start(); - - // スレッドの終了を待機 - thread1.join(); - thread2.join(); - } -} \ No newline at end of file diff --git a/app/backend/api/src/test/java/com/example/sms/service/master/product/ProductRepositoryTest.java b/app/backend/api/src/test/java/com/example/sms/service/master/product/ProductRepositoryTest.java index fc80db0a..83925874 100644 --- a/app/backend/api/src/test/java/com/example/sms/service/master/product/ProductRepositoryTest.java +++ b/app/backend/api/src/test/java/com/example/sms/service/master/product/ProductRepositoryTest.java @@ -10,16 +10,39 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.dao.OptimisticLockingFailureException; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.utility.DockerImageName; import java.util.List; import java.util.Optional; import java.util.stream.IntStream; import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; @SpringBootTest +@Testcontainers +@ActiveProfiles("container") @DisplayName("商品レポジトリ") public class ProductRepositoryTest { + @Container + private static final PostgreSQLContainer postgres = + new PostgreSQLContainer<>(DockerImageName.parse("postgres:15")) + .withUsername("root") + .withPassword("password") + .withDatabaseName("postgres"); + + @DynamicPropertySource + static void setup(DynamicPropertyRegistry registry) { + registry.add("spring.datasource.url", postgres::getJdbcUrl); + } + @Autowired private ProductRepository repository; @@ -110,6 +133,39 @@ void shouldDeleteProduct() { assertEquals(0, repository.selectAll().size()); } + + @Test + @DisplayName("楽観ロックが正常に動作すること") + void testOptimisticLockingWithThreads() throws InterruptedException { + // Productを新規作成して保存 + Product product1 = getProduct("99999999"); + repository.save(product1); + + // 同じIDのProductをもう一度データベースから取得 + repository.findById("99999999").orElseThrow(); + + // スレッド1でproduct1を更新 + Thread thread1 = new Thread(() -> { + Product updatedProduct1 = getProduct("99999999"); + repository.save(updatedProduct1); + }); + + // スレッド2でproduct2を更新し、例外を確認 + Thread thread2 = new Thread(() -> { + Product updatedProduct2 = getProduct("99999999"); + assertThrows(OptimisticLockingFailureException.class, () -> { + repository.save(updatedProduct2); + }); + }); + + // スレッドを開始 + thread1.start(); + thread2.start(); + + // スレッドの終了を待機 + thread1.join(); + thread2.join(); + } } @Nested