From dcc587c13244b90b6bdb3bbfeb469461284cf7d2 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Sun, 4 Aug 2024 21:05:33 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=20=ED=81=B4=EB=A6=AC=EB=84=88=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../support/extension/DatabaseCleaner.java | 36 +++++++++++++++++++ .../extension/DatabaseCleanerExtension.java | 19 ++++++++++ 2 files changed, 55 insertions(+) create mode 100644 server/src/test/java/server/haengdong/support/extension/DatabaseCleaner.java create mode 100644 server/src/test/java/server/haengdong/support/extension/DatabaseCleanerExtension.java diff --git a/server/src/test/java/server/haengdong/support/extension/DatabaseCleaner.java b/server/src/test/java/server/haengdong/support/extension/DatabaseCleaner.java new file mode 100644 index 000000000..2a6d6a3a7 --- /dev/null +++ b/server/src/test/java/server/haengdong/support/extension/DatabaseCleaner.java @@ -0,0 +1,36 @@ +package server.haengdong.support.extension; + +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import java.util.List; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +@Component +class DatabaseCleaner { + + @PersistenceContext + private EntityManager em; + + @Transactional + public void clear() { + em.clear(); + truncate(); + } + + private void truncate() { + em.createNativeQuery("SET REFERENTIAL_INTEGRITY FALSE").executeUpdate(); + getTruncateQueries().forEach(query -> em.createNativeQuery(query).executeUpdate()); + em.createNativeQuery("SET REFERENTIAL_INTEGRITY TRUE").executeUpdate(); + } + + private List getTruncateQueries() { + String sql = """ + SELECT Concat('TRUNCATE TABLE ', TABLE_NAME, ' RESTART IDENTITY', ';') AS q + FROM INFORMATION_SCHEMA.TABLES + WHERE TABLE_SCHEMA = 'PUBLIC' + """; + + return em.createNativeQuery(sql).getResultList(); + } +} diff --git a/server/src/test/java/server/haengdong/support/extension/DatabaseCleanerExtension.java b/server/src/test/java/server/haengdong/support/extension/DatabaseCleanerExtension.java new file mode 100644 index 000000000..653ecadb3 --- /dev/null +++ b/server/src/test/java/server/haengdong/support/extension/DatabaseCleanerExtension.java @@ -0,0 +1,19 @@ +package server.haengdong.support.extension; + +import org.junit.jupiter.api.extension.AfterEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +public class DatabaseCleanerExtension implements AfterEachCallback { + + @Override + public void afterEach(ExtensionContext context) { + DatabaseCleaner databaseCleaner = getDataCleaner(context); + databaseCleaner.clear(); + } + + private DatabaseCleaner getDataCleaner(ExtensionContext extensionContext) { + return SpringExtension.getApplicationContext(extensionContext) + .getBean(DatabaseCleaner.class); + } +} From 3304536bf32aadf4400d5683a0db9aa13cef6d8d Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 5 Aug 2024 15:27:48 +0900 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=ED=81=B4=EB=A6=AC=EB=84=88=20=EC=83=81=EC=88=98,=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../support/extension/DatabaseCleaner.java | 42 +++++++++++++------ 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/server/src/test/java/server/haengdong/support/extension/DatabaseCleaner.java b/server/src/test/java/server/haengdong/support/extension/DatabaseCleaner.java index 2a6d6a3a7..1c83ee4dc 100644 --- a/server/src/test/java/server/haengdong/support/extension/DatabaseCleaner.java +++ b/server/src/test/java/server/haengdong/support/extension/DatabaseCleaner.java @@ -1,5 +1,6 @@ package server.haengdong.support.extension; +import jakarta.annotation.PostConstruct; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; import java.util.List; @@ -9,8 +10,33 @@ @Component class DatabaseCleaner { + private static final String REFERENTIAL_FORMAT = "set referential_integrity %b;"; + private static final String TRUNCATE_FORMAT = "truncate table %s restart identity;"; + @PersistenceContext private EntityManager em; + private String truncateTablesQuery; + + @PostConstruct + public void createTruncateQuery() { + List tableNames = getTableNames(); + StringBuilder stringBuilder = new StringBuilder(); + + for (String tableName : tableNames) { + String truncateQuery = String.format(TRUNCATE_FORMAT, tableName); + stringBuilder.append(truncateQuery); + } + truncateTablesQuery = stringBuilder.toString(); + } + + private List getTableNames() { + String sql = """ + select table_name + from information_schema.tables + where table_schema = 'public' + """; + return em.createNativeQuery(sql).getResultList(); + } @Transactional public void clear() { @@ -19,18 +45,8 @@ public void clear() { } private void truncate() { - em.createNativeQuery("SET REFERENTIAL_INTEGRITY FALSE").executeUpdate(); - getTruncateQueries().forEach(query -> em.createNativeQuery(query).executeUpdate()); - em.createNativeQuery("SET REFERENTIAL_INTEGRITY TRUE").executeUpdate(); - } - - private List getTruncateQueries() { - String sql = """ - SELECT Concat('TRUNCATE TABLE ', TABLE_NAME, ' RESTART IDENTITY', ';') AS q - FROM INFORMATION_SCHEMA.TABLES - WHERE TABLE_SCHEMA = 'PUBLIC' - """; - - return em.createNativeQuery(sql).getResultList(); + em.createNativeQuery(String.format(REFERENTIAL_FORMAT, false)).executeUpdate(); + em.createNativeQuery(truncateTablesQuery).executeUpdate(); + em.createNativeQuery(String.format(REFERENTIAL_FORMAT, true)).executeUpdate(); } } From 1e609c040c1d187c1c2384b600cb5ac3ed28f68f Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 5 Aug 2024 15:35:43 +0900 Subject: [PATCH 3/3] =?UTF-8?q?refactor:=20=EB=8D=B0=EC=9D=B4=ED=84=B0?= =?UTF-8?q?=EB=B2=A0=EC=9D=B4=EC=8A=A4=20=ED=81=B4=EB=A6=AC=EB=84=88=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/ActionServiceTest.java | 16 ++--------- .../application/BillActionServiceTest.java | 14 ++-------- .../application/EventServiceTest.java | 28 ++++++------------- .../application/MemberActionFactoryTest.java | 21 ++++---------- .../application/MemberActionServiceTest.java | 17 +++-------- .../support/extension/DatabaseCleaner.java | 2 +- 6 files changed, 26 insertions(+), 72 deletions(-) diff --git a/server/src/test/java/server/haengdong/application/ActionServiceTest.java b/server/src/test/java/server/haengdong/application/ActionServiceTest.java index a05141b9b..159bdd68e 100644 --- a/server/src/test/java/server/haengdong/application/ActionServiceTest.java +++ b/server/src/test/java/server/haengdong/application/ActionServiceTest.java @@ -7,14 +7,13 @@ import static server.haengdong.domain.action.MemberActionStatus.OUT; import java.util.List; -import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import server.haengdong.application.response.MemberBillReportAppResponse; import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.ActionRepository; import server.haengdong.domain.action.BillAction; import server.haengdong.domain.action.BillActionRepository; import server.haengdong.domain.action.MemberAction; @@ -23,7 +22,9 @@ import server.haengdong.domain.event.EventRepository; import server.haengdong.exception.HaengdongErrorCode; import server.haengdong.exception.HaengdongException; +import server.haengdong.support.extension.DatabaseCleanerExtension; +@ExtendWith(DatabaseCleanerExtension.class) @SpringBootTest class ActionServiceTest { @@ -33,23 +34,12 @@ class ActionServiceTest { @Autowired private EventRepository eventRepository; - @Autowired - private ActionRepository actionRepository; - @Autowired private BillActionRepository billActionRepository; @Autowired private MemberActionRepository memberActionRepository; - @AfterEach - void tearDown() { - billActionRepository.deleteAllInBatch(); - memberActionRepository.deleteAllInBatch(); - actionRepository.deleteAllInBatch(); - eventRepository.deleteAllInBatch(); - } - @DisplayName("참여자별 정산 현황을 조회한다.") @Test void getMemberBillReports() { diff --git a/server/src/test/java/server/haengdong/application/BillActionServiceTest.java b/server/src/test/java/server/haengdong/application/BillActionServiceTest.java index 98e0b13b1..76b576542 100644 --- a/server/src/test/java/server/haengdong/application/BillActionServiceTest.java +++ b/server/src/test/java/server/haengdong/application/BillActionServiceTest.java @@ -6,9 +6,9 @@ import static org.junit.jupiter.api.Assertions.assertAll; import java.util.List; -import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import server.haengdong.application.request.BillActionAppRequest; @@ -20,29 +20,21 @@ import server.haengdong.domain.event.Event; import server.haengdong.domain.event.EventRepository; import server.haengdong.exception.HaengdongException; +import server.haengdong.support.extension.DatabaseCleanerExtension; +@ExtendWith(DatabaseCleanerExtension.class) @SpringBootTest class BillActionServiceTest { @Autowired private BillActionService billActionService; - @Autowired - private ActionRepository actionRepository; - @Autowired private EventRepository eventRepository; @Autowired private BillActionRepository billActionRepository; - @AfterEach - void tearDown() { - billActionRepository.deleteAllInBatch(); - actionRepository.deleteAllInBatch(); - eventRepository.deleteAllInBatch(); - } - @DisplayName("지출 내역을 생성한다.") @Test void saveAllBillAction() { diff --git a/server/src/test/java/server/haengdong/application/EventServiceTest.java b/server/src/test/java/server/haengdong/application/EventServiceTest.java index 5a3e8bce3..e8ba7d22e 100644 --- a/server/src/test/java/server/haengdong/application/EventServiceTest.java +++ b/server/src/test/java/server/haengdong/application/EventServiceTest.java @@ -6,9 +6,9 @@ import static org.mockito.BDDMockito.given; import java.util.List; -import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; @@ -17,7 +17,6 @@ import server.haengdong.application.response.EventAppResponse; import server.haengdong.application.response.EventDetailAppResponse; import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.ActionRepository; import server.haengdong.domain.action.BillAction; import server.haengdong.domain.action.BillActionRepository; import server.haengdong.domain.action.MemberAction; @@ -26,35 +25,26 @@ import server.haengdong.domain.event.Event; import server.haengdong.domain.event.EventRepository; import server.haengdong.domain.event.EventTokenProvider; +import server.haengdong.support.extension.DatabaseCleanerExtension; +@ExtendWith(DatabaseCleanerExtension.class) @SpringBootTest class EventServiceTest { @Autowired private EventService eventService; - @MockBean - private EventTokenProvider eventTokenProvider; - @Autowired private EventRepository eventRepository; - @Autowired - private ActionRepository actionRepository; - @Autowired private BillActionRepository billActionRepository; @Autowired private MemberActionRepository memberActionRepository; - @AfterEach - void tearDown() { - billActionRepository.deleteAllInBatch(); - memberActionRepository.deleteAllInBatch(); - actionRepository.deleteAllInBatch(); - eventRepository.deleteAllInBatch(); - } + @MockBean + private EventTokenProvider eventTokenProvider; @DisplayName("행사를 생성한다") @Test @@ -97,10 +87,10 @@ void findActionsTest() { assertThat(actionAppResponses).hasSize(3) .extracting(ActionAppResponse::actionId, - ActionAppResponse::name, - ActionAppResponse::price, - ActionAppResponse::sequence, - ActionAppResponse::actionTypeName) + ActionAppResponse::name, + ActionAppResponse::price, + ActionAppResponse::sequence, + ActionAppResponse::actionTypeName) .containsExactly( tuple(1L, "토다리", null, 1L, "IN"), tuple(2L, "쿠키", null, 2L, "IN"), diff --git a/server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java b/server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java index 278423759..2c2a978ae 100644 --- a/server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java +++ b/server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java @@ -6,23 +6,24 @@ import static org.assertj.core.api.Assertions.tuple; import java.util.List; -import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import server.haengdong.application.request.MemberActionSaveAppRequest; import server.haengdong.application.request.MemberActionsSaveAppRequest; import server.haengdong.domain.action.Action; import server.haengdong.domain.action.CurrentMembers; -import server.haengdong.domain.event.Event; import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionRepository; import server.haengdong.domain.action.MemberActionStatus; -import server.haengdong.domain.action.ActionRepository; +import server.haengdong.domain.event.Event; import server.haengdong.domain.event.EventRepository; -import server.haengdong.domain.action.MemberActionRepository; import server.haengdong.exception.HaengdongException; +import server.haengdong.support.extension.DatabaseCleanerExtension; +@ExtendWith(DatabaseCleanerExtension.class) @SpringBootTest class MemberActionFactoryTest { @@ -32,19 +33,9 @@ class MemberActionFactoryTest { @Autowired private MemberActionRepository memberActionRepository; - @Autowired - private ActionRepository actionRepository; - @Autowired private EventRepository eventRepository; - @AfterEach - void tearDown() { - memberActionRepository.deleteAllInBatch(); - actionRepository.deleteAllInBatch(); - eventRepository.deleteAllInBatch(); - } - @DisplayName("이전 멤버 액션이 시퀀스 기준으로 정렬되지 않은 상태에서 새로운 멤버 액션 요청을 검증한다.") @Test void createMemberActionsTest() { @@ -80,7 +71,7 @@ void createMemberActionsTest1() { CurrentMembers currentMembers = CurrentMembers.of(List.of(memberAction)); List memberActions = memberActionFactory.createMemberActions(memberActionsSaveAppRequest, - currentMembers, startAction + currentMembers, startAction ); assertThat(memberActions).hasSize(1) diff --git a/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java b/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java index d8b1334fc..5bc9fd1ea 100644 --- a/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java +++ b/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java @@ -8,22 +8,23 @@ import static server.haengdong.domain.action.MemberActionStatus.OUT; import java.util.List; -import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import server.haengdong.application.request.MemberActionSaveAppRequest; import server.haengdong.application.request.MemberActionsSaveAppRequest; import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.ActionRepository; import server.haengdong.domain.action.MemberAction; import server.haengdong.domain.action.MemberActionRepository; import server.haengdong.domain.action.MemberActionStatus; import server.haengdong.domain.event.Event; import server.haengdong.domain.event.EventRepository; import server.haengdong.exception.HaengdongException; +import server.haengdong.support.extension.DatabaseCleanerExtension; +@ExtendWith(DatabaseCleanerExtension.class) @SpringBootTest class MemberActionServiceTest { @@ -36,16 +37,6 @@ class MemberActionServiceTest { @Autowired private EventRepository eventRepository; - @Autowired - private ActionRepository actionRepository; - - @AfterEach - void tearDown() { - memberActionRepository.deleteAllInBatch(); - actionRepository.deleteAllInBatch(); - eventRepository.deleteAllInBatch(); - } - @DisplayName("현재 행사에 참여하고 있는 경우에 나갈 수 있다.") @Test void saveMemberActionTest() { @@ -118,7 +109,7 @@ void deleteMember() { memberActionService.deleteMember(token, "참여자"); List memberActions = memberActionRepository.findAll(); - + assertThat(memberActions).hasSize(5) .extracting("memberName", "status") .containsExactly( diff --git a/server/src/test/java/server/haengdong/support/extension/DatabaseCleaner.java b/server/src/test/java/server/haengdong/support/extension/DatabaseCleaner.java index 1c83ee4dc..346e81d2d 100644 --- a/server/src/test/java/server/haengdong/support/extension/DatabaseCleaner.java +++ b/server/src/test/java/server/haengdong/support/extension/DatabaseCleaner.java @@ -33,7 +33,7 @@ private List getTableNames() { String sql = """ select table_name from information_schema.tables - where table_schema = 'public' + where table_schema = 'PUBLIC' """; return em.createNativeQuery(sql).getResultList(); }