Skip to content

Commit

Permalink
Merge pull request #103 from softeerbootcamp4th/feature/#89-rush-even…
Browse files Browse the repository at this point in the history
…t-test

Feature/#89 rush event test
  • Loading branch information
k000927 authored Aug 12, 2024
2 parents 81cac21 + 2951566 commit 2656472
Show file tree
Hide file tree
Showing 8 changed files with 290 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import JGS.CasperEvent.domain.event.service.adminService.AdminService;
import JGS.CasperEvent.global.response.ResponseDto;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
Expand All @@ -17,14 +17,10 @@

@RestController
@RequestMapping("/admin")
@RequiredArgsConstructor
public class AdminController {
private final AdminService adminService;

@Autowired
public AdminController(AdminService adminService) {
this.adminService = adminService;
}

// 어드민 생성
@PostMapping("/join")
public ResponseEntity<ResponseDto> postAdmin(@RequestBody @Valid AdminRequestDto adminRequestDto) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import JGS.CasperEvent.domain.event.entity.participants.LotteryParticipants;
import JGS.CasperEvent.domain.event.repository.AdminRepository;
import JGS.CasperEvent.domain.event.repository.eventRepository.LotteryEventRepository;
import JGS.CasperEvent.domain.event.repository.eventRepository.RushEventRepository;
import JGS.CasperEvent.domain.event.repository.participantsRepository.LotteryParticipantsRepository;
import JGS.CasperEvent.global.enums.CustomErrorCode;
import JGS.CasperEvent.global.enums.Role;
Expand All @@ -35,7 +34,6 @@ public class AdminService {

private final AdminRepository adminRepository;
private final LotteryEventRepository lotteryEventRepository;
private final RushEventRepository rushEventRepository;
private final LotteryParticipantsRepository lotteryParticipantsRepository;

public Admin verifyAdmin(AdminRequestDto adminRequestDto) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
package JGS.CasperEvent.global.jwt.dto;

import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
public class UserLoginDto {
String phoneNumber;

public UserLoginDto(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,5 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
response.getWriter().write(json);

// HttpServletResponse httpServletResponse = (HttpServletResponse) response;
// httpServletResponse.sendError(HttpStatus.BAD_REQUEST.value());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,5 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
response.getWriter().write(json);

// HttpServletResponse httpServletResponse = (HttpServletResponse) response;
// httpServletResponse.sendError(HttpStatus.BAD_REQUEST.value());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public Jwt createJwt(Map<String, Object> claims) {
.build();
}

public String createToken(Map<String, Object> claims, Date expireDate) {
private String createToken(Map<String, Object> claims, Date expireDate) {
return Jwts.builder()
.setClaims(claims)
.setExpiration(expireDate)
Expand All @@ -39,7 +39,7 @@ public Claims getClaims(String token) {
}


public Date getExpireDateAccessToken() {
private Date getExpireDateAccessToken() {
long expireTimeMils = 1000L * 60 * 60 * 24 * 365;
return new Date(System.currentTimeMillis() + expireTimeMils);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,50 +1,127 @@
package JGS.CasperEvent.domain.event.controller.eventController;

import JGS.CasperEvent.domain.event.entity.event.RushEvent;
import JGS.CasperEvent.domain.event.repository.eventRepository.RushEventRepository;
import JGS.CasperEvent.domain.event.dto.ResponseDto.rushEventResponseDto.*;
import JGS.CasperEvent.domain.event.service.adminService.AdminService;
import JGS.CasperEvent.domain.event.service.eventService.RushEventService;
import JGS.CasperEvent.global.entity.BaseUser;
import JGS.CasperEvent.global.enums.CustomErrorCode;
import JGS.CasperEvent.global.enums.Role;
import JGS.CasperEvent.global.error.exception.CustomException;
import JGS.CasperEvent.global.jwt.service.UserService;
import JGS.CasperEvent.global.jwt.util.JwtProvider;
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.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Profile;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import;
import org.springframework.http.MediaType;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Arrays;

import static org.mockito.BDDMockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@SpringBootTest
@AutoConfigureMockMvc
@ActiveProfiles("local")
class RushEventControllerTest {
@WebMvcTest(RushEventController.class)
@Import(JwtProvider.class)
public class RushEventControllerTest {

@Autowired
private MockMvc mockMvc;

@Autowired
private RushEventRepository rushEventRepository;
@MockBean
private RushEventService rushEventService;

@MockBean
private UserService userService;

@MockBean
private AdminService adminService;

private String phoneNumber;
private String accessToken;

@BeforeEach
void setUp() {
// 테스트 데이터 초기화
rushEventRepository.deleteAll(); // 기존 데이터 삭제
void setUp() throws Exception {
this.phoneNumber = "010-0000-0000";

// userService 모킹
given(userService.verifyUser(any())).willReturn(new BaseUser(this.phoneNumber, Role.USER));

// 액세스 토큰 설정
this.accessToken = getToken(this.phoneNumber);

// Mock 데이터 설정
RushEventListResponseDto rushEventListResponseDto = new RushEventListResponseDto(
Arrays.asList(
new MainRushEventResponseDto(37L, LocalDateTime.of(2024, 8, 11, 22, 0), LocalDateTime.of(2024, 8, 11, 22, 10)),
new MainRushEventResponseDto(38L, LocalDateTime.of(2024, 8, 12, 22, 0), LocalDateTime.of(2024, 8, 12, 22, 10)),
new MainRushEventResponseDto(39L, LocalDateTime.of(2024, 8, 13, 22, 0), LocalDateTime.of(2024, 8, 13, 22, 10)),
new MainRushEventResponseDto(40L, LocalDateTime.of(2024, 8, 14, 22, 0), LocalDateTime.of(2024, 8, 14, 22, 10)),
new MainRushEventResponseDto(41L, LocalDateTime.of(2024, 8, 15, 22, 0), LocalDateTime.of(2024, 8, 15, 22, 10)),
new MainRushEventResponseDto(42L, LocalDateTime.of(2024, 8, 16, 22, 0), LocalDateTime.of(2024, 8, 16, 22, 10))
),
LocalDateTime.of(2024, 8, 12, 13, 46, 29, 48782),
37L,
LocalDate.of(2024, 8, 11),
LocalDate.of(2024, 8, 16),
6L
);

given(rushEventService.getAllRushEvents()).willReturn(rushEventListResponseDto);

MainRushEventOptionsResponseDto mainRushEventOptionsResponseDto = new MainRushEventOptionsResponseDto(
new MainRushEventOptionResponseDto("leftMainText", "leftSubText"),
new MainRushEventOptionResponseDto("rightMainText", "rightSubText")
);

given(rushEventService.getTodayRushEventOptions()).willReturn(mainRushEventOptionsResponseDto);

// 새로운 생성자를 사용한 RushEvent 생성
RushEvent rushEvent1 = new RushEvent("https://example.com/image1.png", "First prize");
RushEvent rushEvent2 = new RushEvent("https://example.com/image2.png", "Second prize");
ResultRushEventOptionResponseDto resultRushEventOptionResponseDto = new ResultRushEventOptionResponseDto(
"mainText",
"resultMainText",
"resultSubText"
);

// 엔티티 저장
rushEventRepository.saveAll(Arrays.asList(rushEvent1, rushEvent2));
given(rushEventService.getRushEventOptionResult(1)).willReturn(resultRushEventOptionResponseDto);
given(rushEventService.getRushEventOptionResult(2)).willReturn(resultRushEventOptionResponseDto);

// 예: apply 메서드가 정상적으로 동작하는 경우 (optionId가 2일 때)
willDoNothing().given(rushEventService).apply(any(BaseUser.class), eq(2));

// 예: apply 메서드가 실패하는 경우 (optionId가 1일 때)
willThrow(new CustomException("이미 응모한 회원입니다.", CustomErrorCode.CONFLICT))
.given(rushEventService).apply(any(BaseUser.class), eq(1));

RushEventRateResponseDto rushEventRateResponseDto = new RushEventRateResponseDto(
1,
315,
1000
);

given(rushEventService.getRushEventRate(any())).willReturn(rushEventRateResponseDto);

RushEventResultResponseDto rushEventResultResponseDto = new RushEventResultResponseDto(
rushEventRateResponseDto,
1,
1000,
315
);

given(rushEventService.getRushEventResult(any())).willReturn(rushEventResultResponseDto);
}

@Test
@DisplayName("메인화면 선착순 이벤트 전체 조회 API 테스트")
public void getRushEventListAndServerTime() throws Exception {
// when
ResultActions perform = mockMvc.perform(get("/event/rush")
Expand All @@ -53,12 +130,144 @@ public void getRushEventListAndServerTime() throws Exception {
// then
perform.andExpect(status().isOk())
.andExpect(jsonPath("$.events").isArray())
.andExpect(jsonPath("$.events.length()").value(2))
.andExpect(jsonPath("$.events[0].prizeImageUrl").value("https://example.com/image1.png"))
.andExpect(jsonPath("$.events[0].prizeDescription").value("First prize"))
.andExpect(jsonPath("$.events[1].prizeImageUrl").value("https://example.com/image2.png"))
.andExpect(jsonPath("$.events[1].prizeDescription").value("Second prize"))
.andExpect(jsonPath("$.serverTime").exists())
.andExpect(jsonPath("$.events.length()").value(6))
.andExpect(jsonPath("$.events[0].rushEventId").value(37))
.andExpect(jsonPath("$.serverTime").value("2024-08-12T13:46:29.000048782"))
.andExpect(jsonPath("$.todayEventId").value(37))
.andExpect(jsonPath("$.eventStartDate").value("2024-08-11"))
.andExpect(jsonPath("$.eventEndDate").value("2024-08-16"))
.andExpect(jsonPath("$.activePeriod").value(6))
.andDo(print());
}

@Test
@DisplayName("오늘의 선착순 이벤트 조회 API 성공 테스트")
public void getTodayEventTest() throws Exception {
// given
String accessToken = this.accessToken;

// when
ResultActions perform = mockMvc.perform(get("/event/rush/today")
.header("Authorization", accessToken)
.contentType(MediaType.APPLICATION_JSON));

// then
perform.andExpect(status().isOk())
.andExpect(jsonPath("$.leftOption.mainText").value("leftMainText"))
.andExpect(jsonPath("$.leftOption.subText").value("leftSubText"))
.andExpect(jsonPath("$.rightOption.mainText").value("rightMainText"))
.andExpect(jsonPath("$.rightOption.subText").value("rightSubText"))
.andDo(print());
}
}


@Test
@DisplayName("응모 성공 테스트 - Option ID 2")
public void applyRushEvent_Success() throws Exception {
String accessToken = this.accessToken;
int optionId = 2;

ResultActions perform = mockMvc.perform(post("/event/rush/options/{optionId}/apply", optionId)
.header("Authorization", accessToken)
.contentType(MediaType.APPLICATION_JSON));

perform.andExpect(status().isNoContent()) // 204 No Content 응답 확인
.andDo(print());
}

@Test
@DisplayName("응모 실패 테스트 - Option ID 1")
public void applyRushEvent_Failure_AlreadyApplied() throws Exception {
String accessToken = this.accessToken;
int optionId = 1;

ResultActions perform = mockMvc.perform(post("/event/rush/options/{optionId}/apply", optionId)
.header("Authorization", accessToken)
.contentType(MediaType.APPLICATION_JSON));

perform.andExpect(status().isConflict()) // 409 Conflict 응답 확인
.andExpect(jsonPath("$.errorCode").value("CONFLICT"))
.andExpect(jsonPath("$.message").value("이미 응모한 회원입니다."))
.andDo(print());
}

@Test
@DisplayName("선택지 결과 조회 성공 테스트")
public void getResultOptionTest() throws Exception {
// given
String accessToken = this.accessToken;

int optionId = 1;

// when
ResultActions perform = mockMvc.perform(get("/event/rush/options/{optionId}/result", optionId)
.header("Authorization", accessToken)
.contentType(MediaType.APPLICATION_JSON));

// then
perform.andExpect(status().isOk())
.andExpect(jsonPath("$.mainText").value("mainText"))
.andExpect(jsonPath("$.resultMainText").value("resultMainText"))
.andExpect(jsonPath("$.resultSubText").value("resultSubText"))
.andDo(print());
}

@Test
@DisplayName("밸런스 게임 비율 조회 API 테스트")
public void getRushEventRateTest() throws Exception {
// given
String accessToken = this.accessToken;

// when
ResultActions perform = mockMvc.perform(get("/event/rush/balance")
.header("Authorization", accessToken)
.contentType(MediaType.APPLICATION_JSON));

// then
perform.andExpect(status().isOk())
.andExpect(jsonPath("$.optionId").value(1))
.andExpect(jsonPath("$.leftOption").value(315))
.andExpect(jsonPath("$.rightOption").value(1000))
.andDo(print());
}

@Test
@DisplayName("밸런스 게임 최종 결과 조회 API 테스트")
public void getRushEventResultTest() throws Exception {
// given
String accessToken = this.accessToken;

// when
ResultActions perform = mockMvc.perform(get("/event/rush/result")
.header("Authorization", accessToken)
.contentType(MediaType.APPLICATION_JSON));

// then
perform.andExpect(status().isOk())
.andExpect(jsonPath("$.leftOption").value(315))
.andExpect(jsonPath("$.rightOption").value(1000))
.andExpect(jsonPath("$.rank").value(1))
.andExpect(jsonPath("$.totalParticipants").value(1000))
.andExpect(jsonPath("$.winnerCount").value(315))
.andDo(print());
}

private String getToken(String phoneNumber) throws Exception {
String requestBody = String.format("""
{
"phoneNumber": "%s"
}
""", phoneNumber);

ResultActions perform = mockMvc.perform(post("/event/auth")
.contentType(MediaType.APPLICATION_JSON)
.content(requestBody));

String jsonString = perform.andReturn().getResponse().getContentAsString();
String tokenPrefix = "\"accessToken\":\"";
int start = jsonString.indexOf(tokenPrefix) + tokenPrefix.length();
int end = jsonString.indexOf("\"", start);

return "Bearer " + jsonString.substring(start, end);
}
}
Loading

0 comments on commit 2656472

Please sign in to comment.