Skip to content

Commit

Permalink
Merge pull request #19 from softeerbootcamp4th/test/arrival
Browse files Browse the repository at this point in the history
[Test] arrival 퀴즈, 선착순 이벤트, 스케줄러 단위테스트 추가
  • Loading branch information
eckrin authored Aug 12, 2024
2 parents 311bbfb + 4a02abd commit 781cfaa
Show file tree
Hide file tree
Showing 18 changed files with 561 additions and 28 deletions.
39 changes: 39 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,44 @@ plugins {
id 'java'
id 'org.springframework.boot' version '3.3.2'
id 'io.spring.dependency-management' version '1.1.6'
id 'jacoco'
}

jacoco {
toolVersion = "0.8.9"
}

/** Jacoco start **/
test {
finalizedBy jacocoTestReport
}

jacocoTestReport {
dependsOn test

reports {
xml.required.set(true)
html.required.set(true)

// QueryDSL Q클래스 제외
def Qdomains = []
for (qPattern in "**/QA".."**/QZ") {
Qdomains.add(qPattern + "*")
}

afterEvaluate {
classDirectories.setFrom(files(classDirectories.files.collect {
fileTree(dir: it,
exclude: [] + Qdomains)
}))
}

xml.destination file("${buildDir}/jacoco/index.xml")
html.destination file("${buildDir}/jacoco/index.html")
}
}
/** Jacoco end **/

group = 'com.softeer'
version = '0.0.1-SNAPSHOT'

Expand Down Expand Up @@ -47,8 +83,11 @@ dependencies {
implementation 'com.nimbusds:nimbus-jose-jwt:9.37.3'
// lombok
annotationProcessor 'org.projectlombok:lombok'
// junit
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
// test h2 database
testRuntimeOnly 'com.h2database:h2'
//redission
implementation 'org.redisson:redisson-spring-boot-starter:3.33.0'
implementation "org.redisson:redisson-spring-data-27:3.33.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@


import com.softeer.podoarrival.common.response.CommonResponse;
import com.softeer.podoarrival.common.response.ErrorCode;
import com.softeer.podoarrival.event.exception.AsyncRequestExecuteException;
import com.softeer.podoarrival.event.exception.ExistingUserException;
import com.softeer.podoarrival.event.model.dto.ArrivalApplicationResponseDto;
import com.softeer.podoarrival.event.service.ArrivalEventReleaseService;
import com.softeer.podoarrival.event.service.ArrivalEventService;
import com.softeer.podoarrival.security.Auth;
import com.softeer.podoarrival.security.AuthInfo;
Expand Down Expand Up @@ -33,10 +32,11 @@ public CompletableFuture<CommonResponse<ArrivalApplicationResponseDto>> arrivalE
return arrivalEventService.applyEvent(authInfo)
.thenApply(result -> new CommonResponse<>(result))
.exceptionally(ex -> {
log.error("비동기 처리 중 오류 발생", ex);
// 예외 발생 시 적절한 오류 응답을 반환
throw new AsyncRequestExecuteException("선착순 요청 중 서버 오류 발생");
if(ex.getCause() instanceof ExistingUserException) {
throw new ExistingUserException("[비동기 에러] 유저가 이미 존재합니다.");
} else {
throw new AsyncRequestExecuteException("[비동기 에러] 선착순 요청 중 서버 오류 발생");
}
});
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Entity
@Table(name = "event_types")
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

Expand All @@ -10,6 +11,7 @@
@Entity
@Table(name = "quizzes")
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Quiz {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.softeer.podoarrival.event.scheduler.scheduler;
package com.softeer.podoarrival.event.scheduler;

import com.softeer.podoarrival.event.exception.EventTypeNotExistsException;
import com.softeer.podoarrival.event.model.entity.Event;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public class ArrivalEventReleaseService {
private final String ARRIVAL_SET = "arrivalset";
private boolean CHECK = false;

private static int MAX_ARRIVAL = 0;
private static int MAX_ARRIVAL = 100; // default

/**
* 비동기로 Redis 호출하는 메서드
Expand All @@ -38,16 +38,15 @@ public class ArrivalEventReleaseService {
@Async("arrivalExecutor")
public CompletableFuture<ArrivalApplicationResponseDto> applyEvent(AuthInfo authInfo) {
return CompletableFuture.supplyAsync(() -> {
LocalDate now = LocalDate.now();
String redisKey = LocalDate.now() + ARRIVAL_SET;

if(CHECK){
return new ArrivalApplicationResponseDto("선착순 응모에 실패했습니다.", -1);
}
log.info("전화번호 = {}", authInfo.getPhoneNum());

RBatch batch = redissonClient.createBatch();
batch.getSet(now + ARRIVAL_SET).addAsync(authInfo.getPhoneNum());
batch.getSet(now + ARRIVAL_SET).sizeAsync();
batch.getSet(redisKey).addAsync(authInfo.getPhoneNum());
batch.getSet(redisKey).sizeAsync();
BatchResult<?> res = batch.execute();

//첫번째 응답
Expand All @@ -66,6 +65,7 @@ public CompletableFuture<ArrivalApplicationResponseDto> applyEvent(AuthInfo auth
.arrivalRank(grade)
.build()
);
log.info("전화번호 = {}", authInfo.getPhoneNum());
return new ArrivalApplicationResponseDto("선착순 응모에 성공했습니다.", grade);
} else {
CHECK = true;
Expand All @@ -77,4 +77,8 @@ public CompletableFuture<ArrivalApplicationResponseDto> applyEvent(AuthInfo auth
public static void setMaxArrival(int val) {
MAX_ARRIVAL = val;
}

public static int getMaxArrival() {
return MAX_ARRIVAL;
}
}
Original file line number Diff line number Diff line change
@@ -1,25 +1,22 @@
package com.softeer.podoarrival.event.service;

import com.softeer.podoarrival.common.response.CommonResponse;
import com.softeer.podoarrival.event.exception.AsyncRequestExecuteException;
import com.softeer.podoarrival.event.model.dto.ArrivalApplicationResponseDto;
import com.softeer.podoarrival.security.AuthInfo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.concurrent.*;
import java.util.concurrent.CompletableFuture;

@Slf4j
@Service
@RequiredArgsConstructor
public class ArrivalEventService {

private final ExecutorService executorService;
private final ArrivalEventReleaseService arrivalEventReleaseService;

@Transactional
public CompletableFuture<ArrivalApplicationResponseDto> applyEvent(AuthInfo authInfo) {
return arrivalEventReleaseService.applyEvent(authInfo);
}
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/com/softeer/podoarrival/security/Auth.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package com.softeer.podoarrival.security;

import io.swagger.v3.oas.annotations.Parameter;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Parameter(hidden = true)
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface Auth {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,22 @@
package com.softeer.podoarrival.event.service;
package com.softeer.podoarrival.integration.event;

import com.softeer.podoarrival.PodoArrivalApplication;
import com.softeer.podoarrival.event.model.dto.ArrivalApplicationResponseDto;
import com.softeer.podoarrival.security.AuthInfo;
import com.softeer.podoarrival.event.model.entity.Role;
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.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ContextConfiguration;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

import static org.junit.jupiter.api.Assertions.*;

import static org.junit.jupiter.api.Assertions.assertEquals;

@SpringBootTest
@ContextConfiguration(classes = PodoArrivalApplication.class)
Expand All @@ -31,12 +30,11 @@ class ArrivalEventServiceTest {

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

@Value("${MAX_COUNT}")
private int MAX_COUNT;
private int MAX_COUNT = 100;

@Test
@DisplayName("선착순 api 정확도 테스트")
Expand Down Expand Up @@ -70,7 +68,6 @@ void applicationTest() throws InterruptedException {
countDownLatch.await();

//then
redissonClient.getSet("arrivalset").clear();
assertEquals(MAX_COUNT, count.get());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.softeer.podoarrival.unit.base;

import com.softeer.podoarrival.event.model.entity.Role;
import com.softeer.podoarrival.event.repository.ArrivalUserRepository;
import com.softeer.podoarrival.event.service.ArrivalEventReleaseService;
import com.softeer.podoarrival.security.AuthInfo;
import org.junit.jupiter.api.BeforeEach;
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.BatchResult;
import org.redisson.api.RBatch;
import org.redisson.api.RSetAsync;
import org.redisson.api.RedissonClient;

@ExtendWith(MockitoExtension.class)
public class ArrivalEventBase {

@Mock
protected RedissonClient redissonClient;

@Mock
protected ArrivalUserRepository arrivalUserRepository;

@Mock
protected RBatch batch;

@Mock
protected RSetAsync<String> setAsync;

@Mock
protected BatchResult<Object> batchResult;

@InjectMocks
protected ArrivalEventReleaseService arrivalEventReleaseService;

protected AuthInfo authInfo;

@BeforeEach
public void setUp() {
authInfo = new AuthInfo("user", "01012345678", Role.ROLE_USER);
ArrivalEventReleaseService.setMaxArrival(5);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.softeer.podoarrival.unit.base;

import com.softeer.podoarrival.event.repository.EventRepository;
import com.softeer.podoarrival.event.repository.EventRewardRepository;
import com.softeer.podoarrival.event.repository.EventTypeRepository;
import com.softeer.podoarrival.event.scheduler.ArrivalEventMaxArrivalScheduler;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
public class ArrivalEventMaxCountSchedulerBase {

@Mock
protected EventRepository eventRepository;

@Mock
protected EventRewardRepository eventRewardRepository;

@Mock
protected EventTypeRepository eventTypeRepository;

@InjectMocks
protected ArrivalEventMaxArrivalScheduler arrivalEventMaxArrivalScheduler;

@BeforeEach
public void setUp() {
}

@AfterEach
public void tearDown() {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.softeer.podoarrival.unit.base;

import com.softeer.podoarrival.event.repository.QuizRepository;
import com.softeer.podoarrival.event.repository.RedisRepository;
import com.softeer.podoarrival.event.scheduler.DailyQuizScheduler;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
public class DailyQuizSchedulerBase {

@Mock
protected RedisRepository redisRepository;

@Mock
protected QuizRepository quizRepository;

@InjectMocks
protected DailyQuizScheduler quizScheduler;

@BeforeEach
public void setUp() {
}

@AfterEach
public void tearDown() {
}
}
Loading

0 comments on commit 781cfaa

Please sign in to comment.