diff --git a/backend/src/main/java/corea/scheduler/domain/AutomaticMatching.java b/backend/src/main/java/corea/scheduler/domain/AutomaticMatching.java index 5fe5aa84a..e5cb757b5 100644 --- a/backend/src/main/java/corea/scheduler/domain/AutomaticMatching.java +++ b/backend/src/main/java/corea/scheduler/domain/AutomaticMatching.java @@ -10,6 +10,12 @@ import java.time.LocalDateTime; @Entity +@Table(name = "automatic_matching", + indexes = { + @Index(name = "idx_room_id", columnList = "room_id"), + @Index(name = "idx_room_status", columnList = "status") + } +) @AllArgsConstructor @NoArgsConstructor(access = AccessLevel.PROTECTED) @Getter diff --git a/backend/src/main/java/corea/scheduler/domain/AutomaticUpdate.java b/backend/src/main/java/corea/scheduler/domain/AutomaticUpdate.java index ec1a75ba6..03a8b2aea 100644 --- a/backend/src/main/java/corea/scheduler/domain/AutomaticUpdate.java +++ b/backend/src/main/java/corea/scheduler/domain/AutomaticUpdate.java @@ -10,6 +10,12 @@ import java.time.LocalDateTime; @Entity +@Table(name = "automatic_update", + indexes = { + @Index(name = "idx_room_id", columnList = "room_id"), + @Index(name = "idx_room_status", columnList = "status") + } +) @AllArgsConstructor @NoArgsConstructor(access = AccessLevel.PROTECTED) @Getter diff --git a/backend/src/test/java/config/TestAsyncConfig.java b/backend/src/test/java/config/TestAsyncConfig.java index a4b671cf4..d20ee801e 100644 --- a/backend/src/test/java/config/TestAsyncConfig.java +++ b/backend/src/test/java/config/TestAsyncConfig.java @@ -2,7 +2,7 @@ import org.springframework.boot.test.context.TestConfiguration; import org.springframework.context.annotation.Bean; -import org.springframework.core.task.SyncTaskExecutor; +import org.springframework.core.task.SimpleAsyncTaskExecutor; import org.springframework.core.task.TaskExecutor; import org.springframework.scheduling.annotation.EnableAsync; @@ -12,6 +12,6 @@ public class TestAsyncConfig { @Bean public TaskExecutor taskExecutor() { - return new SyncTaskExecutor(); + return new SimpleAsyncTaskExecutor(); } } diff --git a/backend/src/test/java/config/TestSyncConfig.java b/backend/src/test/java/config/TestSyncConfig.java new file mode 100644 index 000000000..ab364a17e --- /dev/null +++ b/backend/src/test/java/config/TestSyncConfig.java @@ -0,0 +1,17 @@ +package config; + +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.core.task.SyncTaskExecutor; +import org.springframework.core.task.TaskExecutor; +import org.springframework.scheduling.annotation.EnableAsync; + +@TestConfiguration +@EnableAsync +public class TestSyncConfig { + + @Bean + public TaskExecutor taskExecutor() { + return new SyncTaskExecutor(); + } +} diff --git a/backend/src/test/java/corea/scheduler/service/AutomaticMatchingExecutorTest.java b/backend/src/test/java/corea/scheduler/service/AutomaticMatchingExecutorTest.java index b23447fd6..8768813d9 100644 --- a/backend/src/test/java/corea/scheduler/service/AutomaticMatchingExecutorTest.java +++ b/backend/src/test/java/corea/scheduler/service/AutomaticMatchingExecutorTest.java @@ -22,8 +22,10 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.context.annotation.Import; import java.time.LocalDateTime; @@ -31,10 +33,9 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import java.util.concurrent.atomic.AtomicInteger; -import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.Mockito.when; @ServiceTest @@ -59,16 +60,19 @@ class AutomaticMatchingExecutorTest { @MockBean private PullRequestProvider pullRequestProvider; + @Autowired + private RoomMatchInfoRepository roomMatchInfoRepository; + + @SpyBean + MatchingExecutor matchingExecutor; + private Room room; - private Room emptyParticipantRoom; private Member pororo; private Member ash; private Member joysun; private Member movin; private Member ten; private Member cho; - @Autowired - private RoomMatchInfoRepository roomMatchInfoRepository; @BeforeEach void setUp() { @@ -79,9 +83,9 @@ void setUp() { ten = memberRepository.save(MemberFixture.MEMBER_TENTEN()); cho = memberRepository.save(MemberFixture.MEMBER_CHOCO()); - room = roomRepository.save(RoomFixture.ROOM_DOMAIN(pororo, LocalDateTime.now().plusSeconds(3))); - roomMatchInfoRepository.save(new RoomMatchInfo(room.getId(),true)); - emptyParticipantRoom = roomRepository.save(RoomFixture.ROOM_DOMAIN(ash, LocalDateTime.now().plusSeconds(3))); + room = roomRepository.save(RoomFixture.ROOM_DOMAIN(pororo, LocalDateTime.now() + .plusSeconds(3))); + roomMatchInfoRepository.save(new RoomMatchInfo(room.getId(), true)); participationRepository.save(new Participation(room, pororo, MemberRole.BOTH, room.getMatchingSize())); participationRepository.save(new Participation(room, ash, MemberRole.BOTH, room.getMatchingSize())); @@ -121,17 +125,14 @@ private PullRequestInfo getPullRequestInfo(Member pororo, Member ash, Member joy @Test @DisplayName("동시에 10개의 자동 매칭을 실행해도 PESSIMISTIC_WRITE 락을 통해 동시성을 제어할 수 있다.") void startMatchingWithLock() throws InterruptedException { - AutomaticMatching automaticMatching = automaticMatchingRepository.save(new AutomaticMatching(room.getId(), LocalDateTime.now().plusDays(1))); + AutomaticMatching automaticMatching = automaticMatchingRepository.save(new AutomaticMatching(room.getId(), LocalDateTime.now() + .plusDays(1))); int threadCount = 10; ExecutorService executorService = Executors.newFixedThreadPool(threadCount); CountDownLatch latch = new CountDownLatch(threadCount); - AtomicInteger successCount = new AtomicInteger(0); - when(pullRequestProvider.getUntilDeadline(any(), any())).thenAnswer(ignore -> { - successCount.incrementAndGet(); - return getPullRequestInfo(pororo, ash, joysun, movin, ten, cho); - }); + when(pullRequestProvider.getUntilDeadline(any(), any())).thenReturn(getPullRequestInfo(pororo, ash, joysun, movin, ten, cho)); for (int i = 0; i < threadCount; i++) { executorService.execute(() -> { @@ -144,7 +145,6 @@ void startMatchingWithLock() throws InterruptedException { } latch.await(); - - assertThat(successCount.get()).isEqualTo(1); + Mockito.verify(matchingExecutor,Mockito.times(1)).match(anyLong()); } } diff --git a/backend/src/test/java/corea/scheduler/service/AutomaticUpdateExecutorTest.java b/backend/src/test/java/corea/scheduler/service/AutomaticUpdateExecutorTest.java index e28beafdb..f54aa78e5 100644 --- a/backend/src/test/java/corea/scheduler/service/AutomaticUpdateExecutorTest.java +++ b/backend/src/test/java/corea/scheduler/service/AutomaticUpdateExecutorTest.java @@ -17,8 +17,10 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.context.annotation.Import; import java.time.LocalDateTime; @@ -26,9 +28,7 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import java.util.concurrent.atomic.AtomicInteger; -import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.Mockito.when; @@ -52,6 +52,9 @@ class AutomaticUpdateExecutorTest { @MockBean private MatchResultRepository matchResultRepository; + @SpyBean + UpdateExecutor updateExecutor; + private Room room; @BeforeEach @@ -65,17 +68,15 @@ void setUp() { @Test @DisplayName("동시에 10개의 자동 업데이트를 실행해도 PESSIMISTIC_WRITE 락을 통해 동시성을 제어할 수 있다.") void startMatchingWithLock() throws InterruptedException { - AutomaticUpdate automaticUpdate = automaticUpdateRepository.save(new AutomaticUpdate(room.getId(), LocalDateTime.now().plusDays(1))); + AutomaticUpdate automaticUpdate = automaticUpdateRepository.save(new AutomaticUpdate(room.getId(), LocalDateTime.now() + .plusDays(1))); int threadCount = 10; ExecutorService executorService = Executors.newFixedThreadPool(threadCount); CountDownLatch latch = new CountDownLatch(threadCount); - AtomicInteger successCount = new AtomicInteger(0); - when(matchResultRepository.findAllByRoomIdAndReviewStatus(anyLong(), any(ReviewStatus.class))).thenAnswer(ignore -> { - successCount.incrementAndGet(); - return Collections.singletonList(new MatchResult(room.getId(), MemberFixture.MEMBER_PORORO(), MemberFixture.MEMBER_MOVIN(), "")); - }); + when(matchResultRepository.findAllByRoomIdAndReviewStatus(anyLong(), any(ReviewStatus.class))) + .thenReturn(Collections.singletonList(new MatchResult(room.getId(), MemberFixture.MEMBER_PORORO(), MemberFixture.MEMBER_MOVIN(), ""))); for (int i = 0; i < threadCount; i++) { executorService.execute(() -> { @@ -88,7 +89,6 @@ void startMatchingWithLock() throws InterruptedException { } latch.await(); - - assertThat(successCount.get()).isEqualTo(1); + Mockito.verify(updateExecutor,Mockito.times(1)).update(anyLong()); } } diff --git a/backend/src/test/java/corea/scheduler/service/MatchingExecutorTest.java b/backend/src/test/java/corea/scheduler/service/MatchingExecutorTest.java index c304b9c23..7bab364f7 100644 --- a/backend/src/test/java/corea/scheduler/service/MatchingExecutorTest.java +++ b/backend/src/test/java/corea/scheduler/service/MatchingExecutorTest.java @@ -1,7 +1,7 @@ package corea.scheduler.service; import config.ServiceTest; -import config.TestAsyncConfig; +import config.TestSyncConfig; import corea.alarm.domain.AlarmActionType; import corea.alarm.domain.ServerToUserAlarm; import corea.alarm.repository.ServerToUserAlarmRepository; @@ -42,7 +42,7 @@ import static org.mockito.Mockito.when; @ServiceTest -@Import(TestAsyncConfig.class) +@Import(TestSyncConfig.class) class MatchingExecutorTest { @Autowired diff --git a/backend/src/test/java/corea/scheduler/service/UpdateExecutorTest.java b/backend/src/test/java/corea/scheduler/service/UpdateExecutorTest.java index a566975c7..84da5d0e7 100644 --- a/backend/src/test/java/corea/scheduler/service/UpdateExecutorTest.java +++ b/backend/src/test/java/corea/scheduler/service/UpdateExecutorTest.java @@ -1,7 +1,7 @@ package corea.scheduler.service; import config.ServiceTest; -import config.TestAsyncConfig; +import config.TestSyncConfig; import corea.fixture.MemberFixture; import corea.fixture.RoomFixture; import corea.member.domain.Member; @@ -22,7 +22,7 @@ import static org.assertj.core.api.Assertions.assertThat; @ServiceTest -@Import(TestAsyncConfig.class) +@Import(TestSyncConfig.class) class UpdateExecutorTest { @Autowired