Skip to content

Commit

Permalink
Merge pull request #23 from softeerbootcamp4th/test/arrival-java
Browse files Browse the repository at this point in the history
[Test] Redis, Java 선착순 통합/단위 테스트
  • Loading branch information
eckrin authored Aug 16, 2024
2 parents 3eb767b + f278bdc commit 858f634
Show file tree
Hide file tree
Showing 4 changed files with 219 additions and 21 deletions.
Original file line number Diff line number Diff line change
@@ -1,16 +1,27 @@
package com.softeer.podoarrival.integration.event;

import com.softeer.podoarrival.PodoArrivalApplication;
import com.softeer.podoarrival.event.model.dto.ArrivalApplicationResponseDto;
import com.softeer.podoarrival.event.model.entity.Role;
import com.softeer.podoarrival.event.repository.ArrivalUserRepository;
import com.softeer.podoarrival.event.service.ArrivalEventReleaseServiceJavaImpl;
import com.softeer.podoarrival.event.service.ArrivalEventReleaseServiceRedisImpl;
import com.softeer.podoarrival.event.service.ArrivalEventService;
import com.softeer.podoarrival.security.AuthInfo;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.client.codec.Codec;
import org.redisson.client.codec.StringCodec;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;

import java.util.concurrent.*;
Expand All @@ -19,26 +30,71 @@
import static org.junit.jupiter.api.Assertions.assertEquals;

@SpringBootTest
@ContextConfiguration(classes = PodoArrivalApplication.class)
@ContextConfiguration(classes = {ArrivalEventServiceTest.TestConfig.class})
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
class ArrivalEventServiceTest {

@Autowired
ArrivalEventService arrivalEventService;
@Qualifier("redisEventService")
private ArrivalEventService redisEventService;

@Autowired
RedissonClient redissonClient;
@Qualifier("javaEventService")
private ArrivalEventService javaEventService;

@Autowired
private RedissonClient redissonClient;

@Autowired
private ArrivalUserRepository arrivalUserRepository;

@AfterEach
void tearDown() {
redissonClient.getKeys().deleteByPattern("*arrivalset");
redissonClient.shutdown();
arrivalUserRepository.deleteAllInBatch();
}

private int MAX_COUNT = 100;

@Test
@DisplayName("선착순 api 정확도 테스트")
void applicationTest() throws InterruptedException {
@DisplayName("선착순 api 정확도 테스트 - Redis")
void redisApplyTest() throws InterruptedException {
//given
int threadCount = 100000;
ExecutorService executorService = Executors.newFixedThreadPool(32);
CountDownLatch countDownLatch = new CountDownLatch(threadCount);
AtomicInteger count = new AtomicInteger();

//when
for (int i = 0; i < threadCount; i++) {
long userId = i;
executorService.submit(() -> {
try {
CompletableFuture<ArrivalApplicationResponseDto> futureResponse = redisEventService.applyEvent(
new AuthInfo(
"teat" + userId,
"010-1234-5678-" + userId,
Role.ROLE_USER
)
);
if(futureResponse.get().isSuccess()) count.getAndIncrement();
} catch (ExecutionException | InterruptedException e) {
throw new RuntimeException(e);
} finally {
countDownLatch.countDown();
}
});
}
countDownLatch.await();

//then
assertEquals(MAX_COUNT, count.get());
}

@Test
@DisplayName("선착순 api 정확도 테스트 - Java")
void javaApplyTest() throws InterruptedException {
//given
int threadCount = 100000;
ExecutorService executorService = Executors.newFixedThreadPool(32);
Expand All @@ -50,7 +106,7 @@ void applicationTest() throws InterruptedException {
long userId = i;
executorService.submit(() -> {
try {
CompletableFuture<ArrivalApplicationResponseDto> futureResponse = arrivalEventService.applyEvent(
CompletableFuture<ArrivalApplicationResponseDto> futureResponse = javaEventService.applyEvent(
new AuthInfo(
"teat" + userId,
"010-1234-5678-" + userId,
Expand All @@ -70,4 +126,48 @@ void applicationTest() throws InterruptedException {
//then
assertEquals(MAX_COUNT, count.get());
}

@Configuration
static class TestConfig {

@Bean
@Qualifier("redisEventService")
public ArrivalEventService arrivalEventRedisService(ArrivalEventReleaseServiceRedisImpl arrivalEventReleaseServiceRedisImpl) {
return new ArrivalEventService(arrivalEventReleaseServiceRedisImpl);
}

@Bean
@Qualifier("javaEventService")
public ArrivalEventService arrivalEventJavaService(ArrivalEventReleaseServiceJavaImpl arrivalEventReleaseServiceJavaImpl) {
return new ArrivalEventService(arrivalEventReleaseServiceJavaImpl);
}

@Bean
public ArrivalEventReleaseServiceRedisImpl arrivalEventReleaseServiceRedisImpl() {
return new ArrivalEventReleaseServiceRedisImpl(redisson(), arrivalUserRepository());
}

@Bean
public ArrivalEventReleaseServiceJavaImpl arrivalEventReleaseServiceJavaImpl() {
return new ArrivalEventReleaseServiceJavaImpl(arrivalUserRepository());
}

@Bean
public RedissonClient redisson() {
Config config = new Config();
config.useSingleServer()
.setAddress("redis://127.0.0.1:6379");

// 인코딩 코덱 설정
Codec codec = new StringCodec();
config.setCodec(codec);

return Redisson.create(config);
}

@Bean
public ArrivalUserRepository arrivalUserRepository() {
return Mockito.mock(ArrivalUserRepository.class);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.softeer.podoarrival.unit.base;

import com.softeer.podoarrival.event.model.entity.Event;
import com.softeer.podoarrival.event.model.entity.EventReward;
import com.softeer.podoarrival.event.repository.EventRepository;
import com.softeer.podoarrival.event.repository.EventRewardRepository;
import com.softeer.podoarrival.event.repository.EventTypeRepository;
Expand All @@ -11,6 +13,8 @@
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.time.LocalDateTime;

@ExtendWith(MockitoExtension.class)
public class ArrivalEventMaxCountSchedulerBase {

Expand All @@ -26,8 +30,31 @@ public class ArrivalEventMaxCountSchedulerBase {
@InjectMocks
protected ArrivalEventMaxArrivalScheduler arrivalEventMaxArrivalScheduler;

protected Event eventSample;
protected EventReward eventReward1;
protected EventReward eventReward2;

@BeforeEach
public void setUp() {
eventSample = Event.builder()
.id(1L)
.title("셀토스 선착순 이벤트")
.description("The 2025 셀토스 출시 기념 선착순 이벤트")
.startAt(LocalDateTime.now())
.endAt(LocalDateTime.now().plusDays(5))
.build();

eventReward1 = EventReward.builder()
.id(1L)
.event(eventSample)
.numWinners(10)
.build();

eventReward2 = EventReward.builder()
.id(2L)
.event(eventSample)
.numWinners(50)
.build();
}

@AfterEach
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package com.softeer.podoarrival.unit.event;

import com.softeer.podoarrival.event.model.dto.ArrivalApplicationResponseDto;
import com.softeer.podoarrival.event.model.entity.Role;
import com.softeer.podoarrival.event.repository.ArrivalUserRepository;
import com.softeer.podoarrival.event.service.ArrivalEventReleaseServiceJavaImpl;
import com.softeer.podoarrival.event.service.ArrivalEventReleaseServiceRedisImpl;
import com.softeer.podoarrival.event.service.ArrivalEventService;
import com.softeer.podoarrival.security.AuthInfo;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.redisson.api.RedissonClient;

import java.util.concurrent.CompletableFuture;

import static org.mockito.Mockito.doReturn;

@ExtendWith(MockitoExtension.class)
public class ArrivalEventComplexServiceTest {

@InjectMocks
private ArrivalEventService arrivalEventService;

@Mock
private ArrivalEventReleaseServiceJavaImpl redisService;

@Mock
private ArrivalEventReleaseServiceRedisImpl javaService;

@Mock
private RedissonClient redissonClient;

@Mock
private ArrivalUserRepository arrivalUserRepository;

private AuthInfo authInfo;
private ArrivalApplicationResponseDto expectedResponse;

@BeforeEach
public void setup() {
authInfo = new AuthInfo("name", "phoneNum", Role.ROLE_USER);
expectedResponse = new ArrivalApplicationResponseDto(true, "name", "phoneNum", 1);
}

@Test
@DisplayName("다양한 구현체에 대해 선착순 이벤트 테스트 (성공 - Redis)")
public void testApplyEventWithRedisImplementations_Success() {
// given
doReturn(CompletableFuture.completedFuture(expectedResponse)).when(redisService).applyEvent(authInfo);
arrivalEventService = new ArrivalEventService(redisService);

// when
CompletableFuture<ArrivalApplicationResponseDto> result = arrivalEventService.applyEvent(authInfo);

// then
Assertions.assertThat(result).isCompletedWithValue(expectedResponse);
}

@Test
@DisplayName("다양한 구현체에 대해 선착순 이벤트 테스트 (성공 - Java)")
public void testApplyEventWithJavaImplementations_Success() {
// given
doReturn(CompletableFuture.completedFuture(expectedResponse)).when(javaService).applyEvent(authInfo);
arrivalEventService = new ArrivalEventService(javaService);

// when
CompletableFuture<ArrivalApplicationResponseDto> result = arrivalEventService.applyEvent(authInfo);

// then
Assertions.assertThat(result).isCompletedWithValue(expectedResponse);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

import static org.mockito.ArgumentMatchers.any;
Expand All @@ -32,25 +33,19 @@ public void setArrivalEventCountSuccess_Data_Exists() {
when(eventTypeRepository.findById(1L))
.thenReturn(Optional.ofNullable(arrivalType));
when(eventRepository.findFirstByEventTypeAndStartAtBetween(arrivalType, startOfDay, endOfDay))
.thenReturn(Event.builder()
.id(1L)
.title("셀토스 선착순 이벤트")
.description("The 2025 셀토스 출시 기념 선착순 이벤트")
.startAt(LocalDateTime.now())
.endAt(LocalDateTime.now().plusDays(5))
.build()
);
when(eventRewardRepository.countByEvent(any()))
.thenReturn(50);
.thenReturn(eventSample);
when(eventRewardRepository.findAllByEvent(eventSample))
.thenReturn(List.of(eventReward1, eventReward2));


// when
arrivalEventMaxArrivalScheduler.setEventArrivalCount();

// then
Assertions.assertThat(ArrivalEventReleaseServiceRedisImpl.getMaxArrival())
.isEqualTo(50);
.isEqualTo(60);
Assertions.assertThat(ArrivalEventReleaseServiceJavaImpl.getMaxArrival())
.isEqualTo(50);
.isEqualTo(60);
}

@Test
Expand All @@ -66,8 +61,6 @@ public void setArrivalEventCountSuccess_Data_Not_Exists() {
.thenReturn(Optional.ofNullable(arrivalType));
when(eventRepository.findFirstByEventTypeAndStartAtBetween(any(), any(), any()))
.thenReturn(null);
when(eventRewardRepository.countByEvent(any()))
.thenReturn(0);

// when
arrivalEventMaxArrivalScheduler.setEventArrivalCount();
Expand Down

0 comments on commit 858f634

Please sign in to comment.