Skip to content

Commit

Permalink
Merge pull request #318 from woowacourse-teams/fix/#314
Browse files Browse the repository at this point in the history
[FIX] 중복 투표 예외 처리 및 닉네임 길이 검증 추가
  • Loading branch information
jhon3242 authored Oct 11, 2024
2 parents 924d42c + ce5c1e7 commit 04f306c
Show file tree
Hide file tree
Showing 9 changed files with 70 additions and 107 deletions.
11 changes: 11 additions & 0 deletions backend/src/main/java/ddangkong/domain/room/member/Member.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import ddangkong.domain.room.Room;
import ddangkong.exception.room.member.AlreadyMasterException;
import ddangkong.exception.room.member.InvalidNicknameException;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
Expand All @@ -20,6 +21,9 @@
@Getter
public class Member {

private static final int NICKNAME_MIN_LENGTH = 2;
private static final int NICKNAME_MAX_LENGTH = 12;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
Expand All @@ -35,11 +39,18 @@ public class Member {
private boolean isMaster;

private Member(String nickname, Room room, boolean isMaster) {
validateNickname(nickname);
this.nickname = nickname;
this.room = room;
this.isMaster = isMaster;
}

private void validateNickname(String nickname) {
if (nickname.length() < NICKNAME_MIN_LENGTH || nickname.length() > NICKNAME_MAX_LENGTH) {
throw new InvalidNicknameException(NICKNAME_MIN_LENGTH, NICKNAME_MAX_LENGTH);
}
}

public static Member createMaster(String nickname, Room room) {
return new Member(nickname, room, true);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public enum ClientErrorCode {
NOT_EXIST_COMMON("일반 멤버가 존재하지 않습니다."),
EXCEED_MAX_MEMBER_COUNT("방의 최대 인원을 초과했습니다. 현재 멤버 수: %d"),
NOT_ROOM_MEMBER("방에 존재하지 않는 멤버입니다."),
INVALID_NICKNAME("닉네임은 최소 %d글자, 최대 %d글자여야 합니다."),

// RoomContent
NOT_FOUND_ROOM_CONTENT("방에 존재하지 않는 컨텐츠입니다."),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package ddangkong.exception.room.member;

import static ddangkong.exception.ClientErrorCode.INVALID_NICKNAME;

import ddangkong.exception.BadRequestException;

public class InvalidNicknameException extends BadRequestException {

public InvalidNicknameException(int minLength, int maxLength) {
super(INVALID_NICKNAME.getMessage().formatted(minLength, maxLength));
}

@Override
public String getErrorCode() {
return INVALID_NICKNAME.name();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@
public record RoomJoinRequest(
@NotBlank
String nickname
) { // todo validation 닉네임 정책
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand All @@ -23,11 +24,18 @@ public class RoomBalanceVoteService {

@Transactional
public RoomBalanceVote createVote(Member member, BalanceOptions balanceOptions, Long votedOptionId) {
for (BalanceOption option : balanceOptions.getOptions()) {
validDuplicatedVote(member, option);
}
validDuplicatedVotes(member, balanceOptions);
BalanceOption votedOption = balanceOptions.getOptionById(votedOptionId);
return roomVoteRepository.save(new RoomBalanceVote(member, votedOption));
try {
return roomVoteRepository.save(new RoomBalanceVote(member, votedOption));
} catch (DataIntegrityViolationException e) {
throw new AlreadyVotedException(member.getNickname(), votedOption.getName());
}
}

private void validDuplicatedVotes(Member member, BalanceOptions balanceOptions) {
balanceOptions.getOptions()
.forEach(balanceOption -> validDuplicatedVote(member, balanceOption));
}

private void validDuplicatedVote(Member member, BalanceOption balanceOption) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,30 @@
import static org.junit.jupiter.api.Assertions.assertAll;

import ddangkong.controller.BaseControllerTest;
import ddangkong.controller.exception.ErrorResponse;
import ddangkong.domain.balance.content.BalanceContent;
import ddangkong.domain.balance.content.Category;
import ddangkong.domain.room.Room;
import ddangkong.domain.room.RoomSetting;
import ddangkong.domain.room.RoomStatus;
import ddangkong.domain.room.balance.roomcontent.RoomContent;
import ddangkong.domain.room.member.Member;
import ddangkong.exception.ClientErrorCode;
import ddangkong.facade.room.dto.InitialRoomResponse;
import ddangkong.facade.room.dto.RoomInfoResponse;
import ddangkong.facade.room.dto.RoomJoinRequest;
import ddangkong.facade.room.dto.RoomJoinResponse;
import ddangkong.facade.room.dto.RoomStatusResponse;
import ddangkong.facade.room.dto.RoomSettingRequest;
import ddangkong.facade.room.dto.RoomStatusResponse;
import ddangkong.facade.room.dto.RoundFinishedResponse;
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import java.util.Map;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.springframework.http.HttpStatus;

class RoomControllerTest extends BaseControllerTest {
Expand Down Expand Up @@ -210,38 +214,6 @@ class 방_나가기 {
.then().log().all()
.statusCode(204);
}

@Test
void_식별자가_0이하인_경우_예외를_발생한다() {
// given
Long roomId = 0L;
Long memberId = 1L;

// when & then
RestAssured.given().log().all()
.contentType(ContentType.JSON)
.pathParam("roomId", roomId)
.pathParam("memberId", memberId)
.when().delete(ENDPOINT)
.then().log().all()
.statusCode(400);
}

@Test
void 멤버_식별자가_0이하인_경우_예외를_발생한다() {
// given
Long roomId = 0L;
Long memberId = 1L;

// when & then
RestAssured.given().log().all()
.contentType(ContentType.JSON)
.pathParam("roomId", roomId)
.pathParam("memberId", memberId)
.when().delete(ENDPOINT)
.then().log().all()
.statusCode(400);
}
}

@Nested
Expand All @@ -258,16 +230,6 @@ class 게임_시작 {
.then().log().all()
.statusCode(204);
}

@Test
void 방의_식별자가_음수인_경우_예외를_던진다() {
// when & then
RestAssured.given().log().all()
.pathParam("roomId", -1L)
.when().patch("/api/balances/rooms/{roomId}/start")
.then().log().all()
.statusCode(400);
}
}

@Nested
Expand All @@ -282,16 +244,6 @@ class 다음_라운드_진행 {
.then().log().all()
.statusCode(204);
}

@Test
void 방의_식별자가_음수인_경우_예외를_던진다() {
// when & then
RestAssured.given().log().all()
.pathParam("roomId", -1L)
.when().patch("/api/balances/rooms/{roomId}/next-round")
.then().log().all()
.statusCode(400);
}
}

@Nested
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,5 @@ class 현재_방의_내용_조회 {
// then
assertThat(actual).isEqualTo(EXPECTED_RESPONSE);
}

@Test
void 방의_식별자가_음수인_경우_예외를_던진다() {
// when & then
RestAssured.given().log().all()
.pathParam("roomId", -1L)
.when().get("/api/balances/rooms/{roomId}/content")
.then().log().all()
.statusCode(400);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -88,44 +88,6 @@ class 투표_생성 {
// then
assertThat(actual.optionId()).isEqualTo(optionA.getId());
}

@Test
void 요청_경로의_아이디가_양수가_아닌_경우_400_에러로_응답한다() {
// given
RoomBalanceVoteRequest request = new RoomBalanceVoteRequest(keochan.getId(), optionA.getId());
Long roomId = 0L;

// when & then
assertThatCreateVoteIsBadRequest(roomId, balanceContent.getId(), request);
}

@Test
void 요청_바디의_아이디가_양수가_아닌_경우_400_에러로_응답한다() {
// given
RoomBalanceVoteRequest request = new RoomBalanceVoteRequest(0L, optionA.getId());

// when & then
assertThatCreateVoteIsBadRequest(room.getId(), balanceContent.getId(), request);
}

@Test
void 요청_바디의_아이디가_null_경우_400_에러로_응답한다() {
// given
RoomBalanceVoteRequest request = new RoomBalanceVoteRequest(null, optionA.getId());

// when & then
assertThatCreateVoteIsBadRequest(room.getId(), balanceContent.getId(), request);
}

void assertThatCreateVoteIsBadRequest(Long roomId, Long contentId, RoomBalanceVoteRequest request) {
RestAssured.given().log().all()
.body(request).contentType(ContentType.JSON)
.pathParam("roomId", roomId)
.pathParam("contentId", contentId)
.when().post("/api/balances/rooms/{roomId}/contents/{contentId}/votes")
.then().log().all()
.statusCode(400);
}
}

@Nested
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
package ddangkong.domain.room.member;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatNoException;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

import ddangkong.domain.room.Room;
import ddangkong.domain.support.EntityTestUtils;
import ddangkong.exception.BadRequestException;
import ddangkong.exception.room.member.AlreadyMasterException;
import ddangkong.exception.room.member.InvalidNicknameException;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

class MemberTest {

Expand Down Expand Up @@ -63,4 +66,23 @@ class 일반_유저인지_확인 {
assertThat(actual).isFalse();
}
}

@Nested
class 닉네임_검증 {

@ParameterizedTest
@ValueSource(strings = {"01", "012345678912"})
void 닉네임_길이가_유효한_경우_예외가_발생하지_않는다(String name) {
// when & then
assertThatNoException().isThrownBy(() -> Member.createMaster(name, ROOM));
}

@ParameterizedTest
@ValueSource(strings = {"0", "", "0123456789123"})
void 닉네임_길이가_유효하지_않는_경우_예외를_발생시킨다(String name) {
// when & then
assertThatThrownBy(() -> Member.createMaster(name, ROOM))
.isExactlyInstanceOf(InvalidNicknameException.class);
}
}
}

0 comments on commit 04f306c

Please sign in to comment.