diff --git a/.github/workflows/backend_dev_pr_workflow.yml b/.github/workflows/backend_dev_pr_workflow.yml index 32c17d031..36ba39d66 100644 --- a/.github/workflows/backend_dev_pr_workflow.yml +++ b/.github/workflows/backend_dev_pr_workflow.yml @@ -52,3 +52,16 @@ jobs: - name: Test with Gradle run: ./gradlew test + + - name: 테스트 결과를 PR에 코멘트로 등록합니다 + uses: EnricoMi/publish-unit-test-result-action@v1 + if: always() + with: + files: 'backend/build/test-results/test/TEST-*.xml' + + - name: 테스트 실패 시, 실패한 코드 라인에 Check 코멘트를 등록합니다 + uses: mikepenz/action-junit-report@v3 + if: always() + with: + report_paths: '**/build/test-results/test/TEST-*.xml' + token: ${{ github.token }} diff --git a/backend/src/main/java/com/now/naaga/auth/application/AuthService.java b/backend/src/main/java/com/now/naaga/auth/application/AuthService.java index fb611fd63..4fd9c15f7 100644 --- a/backend/src/main/java/com/now/naaga/auth/application/AuthService.java +++ b/backend/src/main/java/com/now/naaga/auth/application/AuthService.java @@ -9,8 +9,8 @@ import com.now.naaga.auth.infrastructure.dto.MemberAuth; import com.now.naaga.auth.infrastructure.jwt.AuthTokenGenerator; import com.now.naaga.auth.persistence.AuthRepository; -import com.now.naaga.member.application.CreateMemberCommand; -import com.now.naaga.member.application.DeleteMemberCommand; +import com.now.naaga.member.application.dto.CreateMemberCommand; +import com.now.naaga.member.application.dto.DeleteMemberCommand; import com.now.naaga.member.application.MemberService; import com.now.naaga.member.domain.Member; import com.now.naaga.player.application.PlayerService; diff --git a/backend/src/main/java/com/now/naaga/common/MdcFilter.java b/backend/src/main/java/com/now/naaga/common/MdcFilter.java new file mode 100644 index 000000000..66af77323 --- /dev/null +++ b/backend/src/main/java/com/now/naaga/common/MdcFilter.java @@ -0,0 +1,28 @@ +package com.now.naaga.common; + +import jakarta.servlet.*; +import jakarta.servlet.http.HttpServletRequest; +import org.slf4j.MDC; + +import java.io.IOException; +import java.util.UUID; + +import static com.now.naaga.common.MdcToken.*; + +public class MdcFilter implements Filter { + + @Override + public void doFilter(final ServletRequest request, + final ServletResponse response, + final FilterChain chain) + throws IOException, ServletException { + final HttpServletRequest httpServletRequest = (HttpServletRequest) request; + + MDC.put(REQUEST_ID.getKey(), UUID.randomUUID().toString()); + MDC.put(URI.getKey(), httpServletRequest.getRequestURI()); + MDC.put(METHOD.getKey(), httpServletRequest.getMethod()); + + chain.doFilter(request, response); + } + +} diff --git a/backend/src/main/java/com/now/naaga/common/config/BeanConfig.java b/backend/src/main/java/com/now/naaga/common/config/BeanConfig.java index 458c01d39..d6ad7c4a4 100644 --- a/backend/src/main/java/com/now/naaga/common/config/BeanConfig.java +++ b/backend/src/main/java/com/now/naaga/common/config/BeanConfig.java @@ -1,10 +1,10 @@ package com.now.naaga.common.config; import com.fasterxml.jackson.databind.ObjectMapper; -import com.now.naaga.game.domain.gamescore.FailGameScorePolicy; -import com.now.naaga.game.domain.gamescore.GameScoreCalculator; -import com.now.naaga.game.domain.gamescore.GameScorePolicy; -import com.now.naaga.game.domain.gamescore.SuccessGameScorePolicy; +import com.now.naaga.gameresult.domain.gamescore.FailResultScorePolicy; +import com.now.naaga.gameresult.domain.gamescore.ResultScoreCalculator; +import com.now.naaga.gameresult.domain.gamescore.ResultScorePolicy; +import com.now.naaga.gameresult.domain.gamescore.SuccessResultScorePolicy; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @@ -25,21 +25,21 @@ public ObjectMapper objectMapper() { } @Bean - public SuccessGameScorePolicy successGameScorePolicy() { - return new SuccessGameScorePolicy(); + public SuccessResultScorePolicy successGameScorePolicy() { + return new SuccessResultScorePolicy(); } @Bean - public FailGameScorePolicy failGameScorePolicy() { - return new FailGameScorePolicy(); + public FailResultScorePolicy failGameScorePolicy() { + return new FailResultScorePolicy(); } @Bean - public GameScoreCalculator gameScoreCalculator() { - final List gameScorePolicies = List.of( + public ResultScoreCalculator gameScoreCalculator() { + final List gameScorePolicies = List.of( successGameScorePolicy(), failGameScorePolicy() ); - return new GameScoreCalculator(gameScorePolicies); + return new ResultScoreCalculator(gameScorePolicies); } } diff --git a/backend/src/main/java/com/now/naaga/game/application/GameFinishService.java b/backend/src/main/java/com/now/naaga/game/application/GameFinishService.java new file mode 100644 index 000000000..78738c797 --- /dev/null +++ b/backend/src/main/java/com/now/naaga/game/application/GameFinishService.java @@ -0,0 +1,8 @@ +package com.now.naaga.game.application; + +import com.now.naaga.game.application.dto.CreateGameResultCommand; + +public interface GameFinishService { + + void createGameResult(final CreateGameResultCommand createGameResultCommand); +} diff --git a/backend/src/main/java/com/now/naaga/game/application/GameService.java b/backend/src/main/java/com/now/naaga/game/application/GameService.java index 6493288d6..c979a90fa 100644 --- a/backend/src/main/java/com/now/naaga/game/application/GameService.java +++ b/backend/src/main/java/com/now/naaga/game/application/GameService.java @@ -1,16 +1,16 @@ package com.now.naaga.game.application; -import com.now.naaga.game.application.dto.CreateGameCommand; -import com.now.naaga.game.application.dto.EndGameCommand; -import com.now.naaga.game.application.dto.FindAllGamesCommand; -import com.now.naaga.game.application.dto.FindGameByIdCommand; -import com.now.naaga.game.application.dto.FindGameByStatusCommand; +import com.now.naaga.game.application.dto.*; import com.now.naaga.game.domain.*; -import com.now.naaga.game.domain.gamescore.GameScoreCalculator; import com.now.naaga.game.exception.GameException; -import com.now.naaga.game.exception.GameNotArrivalException; +import com.now.naaga.game.exception.GameNotFinishedException; import com.now.naaga.game.repository.GameRepository; -import com.now.naaga.game.repository.GameResultRepository; + +// TODO: 8/31/23 제거할 대상 - 이슈 범위를 벗어나서 일단은 제거하지 않음 +import com.now.naaga.gameresult.domain.GameResult; +import com.now.naaga.gameresult.exception.GameResultException; +import com.now.naaga.gameresult.repository.GameResultRepository; + import com.now.naaga.place.application.PlaceService; import com.now.naaga.place.application.dto.RecommendPlaceCommand; import com.now.naaga.place.domain.Place; @@ -19,7 +19,6 @@ import com.now.naaga.player.application.PlayerService; import com.now.naaga.player.domain.Player; import com.now.naaga.player.presentation.dto.PlayerRequest; -import com.now.naaga.score.domain.Score; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -28,30 +27,34 @@ import static com.now.naaga.game.exception.GameExceptionType.*; +// TODO: 8/31/23 제거할 대상 - 이슈 범위를 벗어나서 일단은 제거하지 않음 +import static com.now.naaga.gameresult.exception.GameResultExceptionType.GAME_RESULT_NOT_EXIST; + @Transactional @Service public class GameService { private final GameRepository gameRepository; + // TODO: 8/31/23 제거할 대상 - 이슈 범위를 벗어나서 일단은 제거하지 않음 private final GameResultRepository gameResultRepository; private final PlayerService playerService; private final PlaceService placeService; - private final GameScoreCalculator gameScoreCalculator; + private final GameFinishService gameFinishService; public GameService(final GameRepository gameRepository, - final GameResultRepository gameResultRepository, - final PlayerService playerService, - final PlaceService placeService, - final GameScoreCalculator gameScoreCalculator) { + final GameResultRepository gameResultRepository, + final PlayerService playerService, + final PlaceService placeService, + final GameFinishService gameFinishService) { this.gameRepository = gameRepository; this.gameResultRepository = gameResultRepository; this.playerService = playerService; this.placeService = placeService; - this.gameScoreCalculator = gameScoreCalculator; + this.gameFinishService = gameFinishService; } public Game createGame(final CreateGameCommand createGameCommand) { @@ -72,16 +75,19 @@ public Game createGame(final CreateGameCommand createGameCommand) { } } - @Transactional(noRollbackFor = {GameNotArrivalException.class}) + @Transactional(noRollbackFor = {GameNotFinishedException.class}) public void endGame(final EndGameCommand endGameCommand) { - final Game game = gameRepository.findById(endGameCommand.gameId()) - .orElseThrow(() -> new GameException(NOT_EXIST)); + final Game game = gameRepository.findById(endGameCommand.gameId()).orElseThrow(() -> new GameException(NOT_EXIST)); final Player player = playerService.findPlayerById(endGameCommand.playerId()); game.validateOwner(player); - final ResultType resultType = game.endGame(endGameCommand.endType(), endGameCommand.position()); - final Score score = gameScoreCalculator.calculate(game, resultType); - player.addScore(score); - gameResultRepository.save(new GameResult(resultType, score, game)); + + final EndType endType = endGameCommand.endType(); + final Position position = endGameCommand.position(); + + game.endGame(position, endType); + + final CreateGameResultCommand createGameResultCommand = new CreateGameResultCommand(player, game, position, endType); + gameFinishService.createGameResult(createGameResultCommand); } @Transactional(readOnly = true) @@ -104,7 +110,7 @@ public GameResult findGameResultByGameId(final Long gameId) { final List gameResultsByGameId = gameResultRepository.findByGameId(gameId); if (gameResultsByGameId.isEmpty()) { - throw new GameException(GAME_RESULT_NOT_EXIST); + throw new GameResultException(GAME_RESULT_NOT_EXIST); } return gameResultsByGameId.get(0); diff --git a/backend/src/main/java/com/now/naaga/game/application/dto/CreateGameResultCommand.java b/backend/src/main/java/com/now/naaga/game/application/dto/CreateGameResultCommand.java new file mode 100644 index 000000000..f6aff4c18 --- /dev/null +++ b/backend/src/main/java/com/now/naaga/game/application/dto/CreateGameResultCommand.java @@ -0,0 +1,13 @@ +package com.now.naaga.game.application.dto; + +import com.now.naaga.game.domain.EndType; +import com.now.naaga.game.domain.Game; +import com.now.naaga.place.domain.Position; +import com.now.naaga.player.domain.Player; + +// TODO: 8/31/23 player -> ID / game -> game -> ID +public record CreateGameResultCommand(Player player, + Game game, + Position position, + EndType endType) { +} diff --git a/backend/src/main/java/com/now/naaga/game/domain/Game.java b/backend/src/main/java/com/now/naaga/game/domain/Game.java index 6babb5835..2ddb4b9ae 100644 --- a/backend/src/main/java/com/now/naaga/game/domain/Game.java +++ b/backend/src/main/java/com/now/naaga/game/domain/Game.java @@ -1,39 +1,24 @@ package com.now.naaga.game.domain; -import static com.now.naaga.game.domain.EndType.GIVE_UP; -import static com.now.naaga.game.domain.GameStatus.DONE; -import static com.now.naaga.game.domain.GameStatus.IN_PROGRESS; -import static com.now.naaga.game.domain.ResultType.FAIL; -import static com.now.naaga.game.domain.ResultType.SUCCESS; -import static com.now.naaga.game.exception.GameExceptionType.ALREADY_DONE; -import static com.now.naaga.game.exception.GameExceptionType.INACCESSIBLE_AUTHENTICATION; -import static com.now.naaga.game.exception.GameExceptionType.NOT_ARRIVED; - import com.now.naaga.common.domain.BaseEntity; import com.now.naaga.game.exception.GameException; -import com.now.naaga.game.exception.GameNotArrivalException; +import com.now.naaga.game.exception.GameExceptionType; +import com.now.naaga.game.exception.GameNotFinishedException; import com.now.naaga.place.domain.Place; import com.now.naaga.place.domain.Position; import com.now.naaga.player.domain.Player; -import jakarta.persistence.AttributeOverride; -import jakarta.persistence.AttributeOverrides; -import jakarta.persistence.Column; -import jakarta.persistence.Embedded; -import jakarta.persistence.Entity; -import jakarta.persistence.EnumType; -import jakarta.persistence.Enumerated; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; -import jakarta.persistence.OneToMany; -import java.math.BigDecimal; +import jakarta.persistence.*; + import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import java.util.Objects; -import org.springframework.data.geo.Distance; + +import static com.now.naaga.game.domain.EndType.ARRIVED; +import static com.now.naaga.game.domain.EndType.GIVE_UP; +import static com.now.naaga.game.domain.GameStatus.DONE; +import static com.now.naaga.game.domain.GameStatus.IN_PROGRESS; +import static com.now.naaga.game.exception.GameExceptionType.*; @Entity public class Game extends BaseEntity { @@ -76,7 +61,9 @@ public class Game extends BaseEntity { protected Game() { } - public Game(final Player player, final Place place, final Position startPosition) { + public Game(final Player player, + final Place place, + final Position startPosition) { this(null, IN_PROGRESS, player, place, startPosition, MAX_ATTEMPT_COUNT, new ArrayList<>(), LocalDateTime.now(), null); } @@ -121,56 +108,62 @@ public boolean canUseMoreHint() { return hints.size() < MAX_HINT_COUNT; } - public ResultType endGame(final EndType endType, final Position position) { - if (isDone()) { - throw new GameException(ALREADY_DONE); - } - if (endType == GIVE_UP) { - return giveUpGame(); - } - return endGameByArrival(position); + public double findDistance() { + final Position destinationPosition = place.getPosition(); + return startPosition.calculateDistance(destinationPosition); } - private boolean isDone() { - return gameStatus == DONE; + public void endGame(final Position position, + final EndType endType) { + validateInProgressing(); + + if (endType == ARRIVED) { + subtractAttempts(); + } + + setGameStatusDone(position, endType); } - private ResultType giveUpGame() { - gameStatus = DONE; - endTime = LocalDateTime.now(); - return FAIL; + private void validateInProgressing() { + if (gameStatus == DONE) { + throw new GameException(ALREADY_DONE); + } } - private ResultType endGameByArrival(final Position position) { + private void subtractAttempts() { + validateAvailableAttempts(); remainingAttempts--; - if (isPlayerArrived(position)) { - return endGameWithSuccess(); - } - return endGameWithFailure(); } - private boolean isPlayerArrived(final Position position) { - return place.isCoordinateInsideBounds(position); + private void validateAvailableAttempts() { + if (remainingAttempts <= 0) { + throw new GameException(GameExceptionType.NOT_REMAIN_ATTEMPTS); + } } - private ResultType endGameWithSuccess() { - gameStatus = DONE; - endTime = LocalDateTime.now(); - return SUCCESS; + private void setGameStatusDone(final Position position, + final EndType endType) { + validateForEnd(position, endType); + + this.endTime = LocalDateTime.now(); + this.gameStatus = DONE; } - private ResultType endGameWithFailure() { - if (remainingAttempts == 0) { - gameStatus = DONE; - endTime = LocalDateTime.now(); - return FAIL; + private void validateForEnd(final Position position, + final EndType endType) { + final boolean isUnfinishedCondition = remainingAttempts > 0 + && !place.isCoordinateInsideBounds(position) + && endType != GIVE_UP; + + if (isUnfinishedCondition) { + throw new GameNotFinishedException(NOT_ARRIVED); } - throw new GameNotArrivalException(NOT_ARRIVED); } - - public double findDistance() { - final Position destinationPosition = place.getPosition(); - return startPosition.calculateDistance(destinationPosition); + + public void validateDoneGame() { + if(gameStatus == IN_PROGRESS) { + throw new GameException(NOT_DONE); + } } public Long getId() { diff --git a/backend/src/main/java/com/now/naaga/game/domain/GameRecord.java b/backend/src/main/java/com/now/naaga/game/domain/GameRecord.java index d1c807d56..d164dc477 100644 --- a/backend/src/main/java/com/now/naaga/game/domain/GameRecord.java +++ b/backend/src/main/java/com/now/naaga/game/domain/GameRecord.java @@ -2,11 +2,10 @@ import static com.now.naaga.game.domain.Game.MAX_ATTEMPT_COUNT; +import com.now.naaga.gameresult.domain.GameResult; import com.now.naaga.place.domain.Position; import java.time.Duration; import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.temporal.ChronoUnit; public class GameRecord { diff --git a/backend/src/main/java/com/now/naaga/game/domain/ResultType.java b/backend/src/main/java/com/now/naaga/game/domain/ResultType.java deleted file mode 100644 index 83ca772f1..000000000 --- a/backend/src/main/java/com/now/naaga/game/domain/ResultType.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.now.naaga.game.domain; - -public enum ResultType { - - SUCCESS, - FAIL, -} diff --git a/backend/src/main/java/com/now/naaga/game/domain/Statistic.java b/backend/src/main/java/com/now/naaga/game/domain/Statistic.java index eded755b2..75ba9a444 100644 --- a/backend/src/main/java/com/now/naaga/game/domain/Statistic.java +++ b/backend/src/main/java/com/now/naaga/game/domain/Statistic.java @@ -3,8 +3,8 @@ import java.time.Duration; import java.util.List; -import static com.now.naaga.game.domain.ResultType.FAIL; -import static com.now.naaga.game.domain.ResultType.SUCCESS; +import static com.now.naaga.gameresult.domain.ResultType.FAIL; +import static com.now.naaga.gameresult.domain.ResultType.SUCCESS; public class Statistic { diff --git a/backend/src/main/java/com/now/naaga/game/exception/GameExceptionType.java b/backend/src/main/java/com/now/naaga/game/exception/GameExceptionType.java index ebcbb0e4e..87df21fa2 100644 --- a/backend/src/main/java/com/now/naaga/game/exception/GameExceptionType.java +++ b/backend/src/main/java/com/now/naaga/game/exception/GameExceptionType.java @@ -41,10 +41,10 @@ public enum GameExceptionType implements BaseExceptionType { "이미 종료된 게임입니다." ), - GAME_RESULT_NOT_EXIST( - 434, - HttpStatus.NOT_FOUND, - "해당게임의 게임결과가 존재하지 않습니다." + NOT_DONE( + 417, + HttpStatus.BAD_REQUEST, + "아직 종료되지 않은 게임입니다." ), HINT_NOT_EXIST_IN_GAME( @@ -58,6 +58,12 @@ public enum GameExceptionType implements BaseExceptionType { HttpStatus.BAD_REQUEST, "사용할 수 있는 힌트를 모두 소진했습니다." ), + + NOT_REMAIN_ATTEMPTS( + 418, + HttpStatus.BAD_REQUEST, + "시도 횟수를 이미 다 사용한 게임입니다" + ), ; private final int errorCode; diff --git a/backend/src/main/java/com/now/naaga/game/exception/GameNotArrivalException.java b/backend/src/main/java/com/now/naaga/game/exception/GameNotArrivalException.java deleted file mode 100644 index 7ce3e9208..000000000 --- a/backend/src/main/java/com/now/naaga/game/exception/GameNotArrivalException.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.now.naaga.game.exception; - -public class GameNotArrivalException extends GameException{ - - public GameNotArrivalException(GameExceptionType gameExceptionType) { - super(gameExceptionType); - } -} diff --git a/backend/src/main/java/com/now/naaga/game/exception/GameNotFinishedException.java b/backend/src/main/java/com/now/naaga/game/exception/GameNotFinishedException.java new file mode 100644 index 000000000..06a19641d --- /dev/null +++ b/backend/src/main/java/com/now/naaga/game/exception/GameNotFinishedException.java @@ -0,0 +1,8 @@ +package com.now.naaga.game.exception; + +public class GameNotFinishedException extends GameException{ + + public GameNotFinishedException(GameExceptionType gameExceptionType) { + super(gameExceptionType); + } +} diff --git a/backend/src/main/java/com/now/naaga/game/presentation/dto/GameResultResponse.java b/backend/src/main/java/com/now/naaga/game/presentation/dto/GameResultResponse.java index b564b4db4..5720c56c5 100644 --- a/backend/src/main/java/com/now/naaga/game/presentation/dto/GameResultResponse.java +++ b/backend/src/main/java/com/now/naaga/game/presentation/dto/GameResultResponse.java @@ -1,9 +1,7 @@ package com.now.naaga.game.presentation.dto; import com.now.naaga.game.domain.GameRecord; -import com.now.naaga.game.domain.ResultType; - -import java.time.LocalDateTime; +import com.now.naaga.gameresult.domain.ResultType; public record GameResultResponse(Long id, Long gameId, diff --git a/backend/src/main/java/com/now/naaga/gameresult/application/GameResultService.java b/backend/src/main/java/com/now/naaga/gameresult/application/GameResultService.java new file mode 100644 index 000000000..010b295ad --- /dev/null +++ b/backend/src/main/java/com/now/naaga/gameresult/application/GameResultService.java @@ -0,0 +1,55 @@ +package com.now.naaga.gameresult.application; + +import com.now.naaga.game.application.dto.CreateGameResultCommand; +import com.now.naaga.game.domain.EndType; +import com.now.naaga.game.domain.Game; +import com.now.naaga.game.application.GameFinishService; +import com.now.naaga.gameresult.domain.GameResult; +import com.now.naaga.gameresult.domain.ResultType; +import com.now.naaga.gameresult.domain.gamescore.ResultScoreCalculator; +import com.now.naaga.gameresult.repository.GameResultRepository; +import com.now.naaga.place.domain.Position; +import com.now.naaga.player.application.PlayerService; +import com.now.naaga.player.application.dto.AddScoreCommand; +import com.now.naaga.player.domain.Player; +import com.now.naaga.score.domain.Score; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Transactional +@Service +public class GameResultService implements GameFinishService { + + private final GameResultRepository gameResultRepository; + + private final PlayerService playerService; + + private final ResultScoreCalculator resultScoreCalculator; + + public GameResultService(final GameResultRepository gameResultRepository, + final PlayerService playerService, + final ResultScoreCalculator resultScoreCalculator) { + this.gameResultRepository = gameResultRepository; + this.playerService = playerService; + this.resultScoreCalculator = resultScoreCalculator; + } + + @Override + public void createGameResult(final CreateGameResultCommand createGameResultCommand) { + final Player player = createGameResultCommand.player(); + final Game game = createGameResultCommand.game(); + game.validateOwner(player); + + final EndType endType = createGameResultCommand.endType(); + final Position position = createGameResultCommand.position(); + + final ResultType resultType = ResultType.decide(game, endType, position); + final Score score = resultScoreCalculator.calculate(game, resultType); + + final AddScoreCommand addScoreCommand = new AddScoreCommand(player.getId(), score); + playerService.addScore(addScoreCommand); + + final GameResult gameResult = new GameResult(resultType, score, game); + gameResultRepository.save(gameResult); + } +} diff --git a/backend/src/main/java/com/now/naaga/game/domain/GameResult.java b/backend/src/main/java/com/now/naaga/gameresult/domain/GameResult.java similarity index 96% rename from backend/src/main/java/com/now/naaga/game/domain/GameResult.java rename to backend/src/main/java/com/now/naaga/gameresult/domain/GameResult.java index 3ed81d94e..33d8f98b2 100644 --- a/backend/src/main/java/com/now/naaga/game/domain/GameResult.java +++ b/backend/src/main/java/com/now/naaga/gameresult/domain/GameResult.java @@ -1,6 +1,7 @@ -package com.now.naaga.game.domain; +package com.now.naaga.gameresult.domain; import com.now.naaga.common.domain.BaseEntity; +import com.now.naaga.game.domain.Game; import com.now.naaga.score.domain.Score; import jakarta.persistence.Embedded; import jakarta.persistence.Entity; diff --git a/backend/src/main/java/com/now/naaga/gameresult/domain/ResultType.java b/backend/src/main/java/com/now/naaga/gameresult/domain/ResultType.java new file mode 100644 index 000000000..8b5d86c33 --- /dev/null +++ b/backend/src/main/java/com/now/naaga/gameresult/domain/ResultType.java @@ -0,0 +1,23 @@ +package com.now.naaga.gameresult.domain; + +import com.now.naaga.game.domain.EndType; +import com.now.naaga.game.domain.Game; +import com.now.naaga.place.domain.Position; + +public enum ResultType { + + SUCCESS, + FAIL, + ; + + public static ResultType decide(final Game game, + final EndType endType, + final Position position) { + game.validateDoneGame(); + + if (endType == EndType.ARRIVED && game.getPlace().isCoordinateInsideBounds(position)) { + return ResultType.SUCCESS; + } + return ResultType.FAIL; + } +} diff --git a/backend/src/main/java/com/now/naaga/game/domain/gamescore/FailGameScorePolicy.java b/backend/src/main/java/com/now/naaga/gameresult/domain/gamescore/FailResultScorePolicy.java similarity index 57% rename from backend/src/main/java/com/now/naaga/game/domain/gamescore/FailGameScorePolicy.java rename to backend/src/main/java/com/now/naaga/gameresult/domain/gamescore/FailResultScorePolicy.java index 66c3a6049..90a0457ca 100644 --- a/backend/src/main/java/com/now/naaga/game/domain/gamescore/FailGameScorePolicy.java +++ b/backend/src/main/java/com/now/naaga/gameresult/domain/gamescore/FailResultScorePolicy.java @@ -1,12 +1,12 @@ -package com.now.naaga.game.domain.gamescore; +package com.now.naaga.gameresult.domain.gamescore; import com.now.naaga.game.domain.Game; -import com.now.naaga.game.domain.ResultType; +import com.now.naaga.gameresult.domain.ResultType; import com.now.naaga.score.domain.Score; -import static com.now.naaga.game.domain.ResultType.FAIL; +import static com.now.naaga.gameresult.domain.ResultType.FAIL; -public class FailGameScorePolicy implements GameScorePolicy { +public class FailResultScorePolicy implements ResultScorePolicy { @Override public Score calculate(final Game game) { diff --git a/backend/src/main/java/com/now/naaga/game/domain/gamescore/GameScoreCalculator.java b/backend/src/main/java/com/now/naaga/gameresult/domain/gamescore/ResultScoreCalculator.java similarity index 60% rename from backend/src/main/java/com/now/naaga/game/domain/gamescore/GameScoreCalculator.java rename to backend/src/main/java/com/now/naaga/gameresult/domain/gamescore/ResultScoreCalculator.java index 6e909e05a..d1db814ef 100644 --- a/backend/src/main/java/com/now/naaga/game/domain/gamescore/GameScoreCalculator.java +++ b/backend/src/main/java/com/now/naaga/gameresult/domain/gamescore/ResultScoreCalculator.java @@ -1,28 +1,28 @@ -package com.now.naaga.game.domain.gamescore; +package com.now.naaga.gameresult.domain.gamescore; import com.now.naaga.common.exception.InternalException; import com.now.naaga.game.domain.Game; -import com.now.naaga.game.domain.ResultType; +import com.now.naaga.gameresult.domain.ResultType; import com.now.naaga.score.domain.Score; import java.util.List; import static com.now.naaga.common.exception.InternalExceptionType.FAIL_ESTABLISH_GAME_SCORE_POLICY; -public class GameScoreCalculator { +public class ResultScoreCalculator { - private final List scorePolicies; + private final List scorePolicies; - public GameScoreCalculator(final List scorePolicies) { + public ResultScoreCalculator(final List scorePolicies) { this.scorePolicies = scorePolicies; } public Score calculate(final Game game, final ResultType resultType) { - final GameScorePolicy gameScorePolicy = scorePolicies.stream() + final ResultScorePolicy resultScorePolicy = scorePolicies.stream() .filter(policy -> policy.hasSameResultType(resultType)) .findAny() .orElseThrow(() -> new InternalException(FAIL_ESTABLISH_GAME_SCORE_POLICY)); - return gameScorePolicy.calculate(game); + return resultScorePolicy.calculate(game); } } diff --git a/backend/src/main/java/com/now/naaga/game/domain/gamescore/GameScorePolicy.java b/backend/src/main/java/com/now/naaga/gameresult/domain/gamescore/ResultScorePolicy.java similarity index 57% rename from backend/src/main/java/com/now/naaga/game/domain/gamescore/GameScorePolicy.java rename to backend/src/main/java/com/now/naaga/gameresult/domain/gamescore/ResultScorePolicy.java index fd669845a..411857437 100644 --- a/backend/src/main/java/com/now/naaga/game/domain/gamescore/GameScorePolicy.java +++ b/backend/src/main/java/com/now/naaga/gameresult/domain/gamescore/ResultScorePolicy.java @@ -1,10 +1,10 @@ -package com.now.naaga.game.domain.gamescore; +package com.now.naaga.gameresult.domain.gamescore; import com.now.naaga.game.domain.Game; -import com.now.naaga.game.domain.ResultType; +import com.now.naaga.gameresult.domain.ResultType; import com.now.naaga.score.domain.Score; -public interface GameScorePolicy { +public interface ResultScorePolicy { Score calculate(final Game game); diff --git a/backend/src/main/java/com/now/naaga/game/domain/gamescore/SuccessGameScorePolicy.java b/backend/src/main/java/com/now/naaga/gameresult/domain/gamescore/SuccessResultScorePolicy.java similarity index 91% rename from backend/src/main/java/com/now/naaga/game/domain/gamescore/SuccessGameScorePolicy.java rename to backend/src/main/java/com/now/naaga/gameresult/domain/gamescore/SuccessResultScorePolicy.java index 2eb1e2d54..3827c3d1e 100644 --- a/backend/src/main/java/com/now/naaga/game/domain/gamescore/SuccessGameScorePolicy.java +++ b/backend/src/main/java/com/now/naaga/gameresult/domain/gamescore/SuccessResultScorePolicy.java @@ -1,7 +1,7 @@ -package com.now.naaga.game.domain.gamescore; +package com.now.naaga.gameresult.domain.gamescore; import com.now.naaga.game.domain.Game; -import com.now.naaga.game.domain.ResultType; +import com.now.naaga.gameresult.domain.ResultType; import com.now.naaga.score.domain.Score; import java.time.Duration; @@ -9,9 +9,9 @@ import static com.now.naaga.game.domain.Game.MAX_ATTEMPT_COUNT; import static com.now.naaga.game.domain.Game.MAX_HINT_COUNT; -import static com.now.naaga.game.domain.ResultType.SUCCESS; +import static com.now.naaga.gameresult.domain.ResultType.SUCCESS; -public class SuccessGameScorePolicy implements GameScorePolicy { +public class SuccessResultScorePolicy implements ResultScorePolicy { private static final Score BASE_SCORE = new Score(50); private static final double HINT_SCORE_RATIO = 0.3; diff --git a/backend/src/main/java/com/now/naaga/gameresult/exception/GameResultException.java b/backend/src/main/java/com/now/naaga/gameresult/exception/GameResultException.java new file mode 100644 index 000000000..2200ac3ad --- /dev/null +++ b/backend/src/main/java/com/now/naaga/gameresult/exception/GameResultException.java @@ -0,0 +1,18 @@ +package com.now.naaga.gameresult.exception; + +import com.now.naaga.common.exception.BaseException; +import com.now.naaga.common.exception.BaseExceptionType; + +public class GameResultException extends BaseException { + + private final GameResultExceptionType gameResultExceptionType; + + public GameResultException(final GameResultExceptionType gameResultExceptionType) { + this.gameResultExceptionType = gameResultExceptionType; + } + + @Override + public BaseExceptionType exceptionType() { + return gameResultExceptionType; + } +} diff --git a/backend/src/main/java/com/now/naaga/gameresult/exception/GameResultExceptionType.java b/backend/src/main/java/com/now/naaga/gameresult/exception/GameResultExceptionType.java new file mode 100644 index 000000000..454c2d8d3 --- /dev/null +++ b/backend/src/main/java/com/now/naaga/gameresult/exception/GameResultExceptionType.java @@ -0,0 +1,41 @@ +package com.now.naaga.gameresult.exception; + +import com.now.naaga.common.exception.BaseExceptionType; +import org.springframework.http.HttpStatus; + +public enum GameResultExceptionType implements BaseExceptionType { + + GAME_RESULT_NOT_EXIST( + 434, + HttpStatus.NOT_FOUND, + "해당게임의 게임결과가 존재하지 않습니다." + ), + ; + + private final int errorCode; + private final HttpStatus httpStatus; + private final String errorMessage; + + GameResultExceptionType(final int errorCode, + final HttpStatus httpStatus, + final String errorMessage) { + this.errorCode = errorCode; + this.httpStatus = httpStatus; + this.errorMessage = errorMessage; + } + + @Override + public int errorCode() { + return errorCode; + } + + @Override + public HttpStatus httpStatus() { + return httpStatus; + } + + @Override + public String errorMessage() { + return errorMessage; + } +} diff --git a/backend/src/main/java/com/now/naaga/game/repository/GameResultRepository.java b/backend/src/main/java/com/now/naaga/gameresult/repository/GameResultRepository.java similarity index 70% rename from backend/src/main/java/com/now/naaga/game/repository/GameResultRepository.java rename to backend/src/main/java/com/now/naaga/gameresult/repository/GameResultRepository.java index 03dc25d44..b61e8e2bb 100644 --- a/backend/src/main/java/com/now/naaga/game/repository/GameResultRepository.java +++ b/backend/src/main/java/com/now/naaga/gameresult/repository/GameResultRepository.java @@ -1,6 +1,6 @@ -package com.now.naaga.game.repository; +package com.now.naaga.gameresult.repository; -import com.now.naaga.game.domain.GameResult; +import com.now.naaga.gameresult.domain.GameResult; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; diff --git a/backend/src/main/java/com/now/naaga/member/application/MemberService.java b/backend/src/main/java/com/now/naaga/member/application/MemberService.java index c3b649119..eb1996554 100644 --- a/backend/src/main/java/com/now/naaga/member/application/MemberService.java +++ b/backend/src/main/java/com/now/naaga/member/application/MemberService.java @@ -2,7 +2,8 @@ import static com.now.naaga.member.exception.MemberExceptionType.NOT_EXIST_MEMBER; -import com.now.naaga.auth.infrastructure.dto.MemberAuth; +import com.now.naaga.member.application.dto.CreateMemberCommand; +import com.now.naaga.member.application.dto.DeleteMemberCommand; import com.now.naaga.member.domain.Member; import com.now.naaga.member.exception.MemberException; import com.now.naaga.member.persistence.repository.MemberRepository; @@ -39,8 +40,6 @@ public Member create(final CreateMemberCommand createMemberCommand) { public void deleteByMemberId(final DeleteMemberCommand deleteMemberCommand) { final Long memberId = deleteMemberCommand.memberId(); - System.out.println("=---------------------------"); - System.out.println(memberId); final Member member = memberRepository.findById(memberId) .orElseThrow(() -> new MemberException(NOT_EXIST_MEMBER)); memberRepository.delete(member); diff --git a/backend/src/main/java/com/now/naaga/member/application/CreateMemberCommand.java b/backend/src/main/java/com/now/naaga/member/application/dto/CreateMemberCommand.java similarity index 53% rename from backend/src/main/java/com/now/naaga/member/application/CreateMemberCommand.java rename to backend/src/main/java/com/now/naaga/member/application/dto/CreateMemberCommand.java index a9b305085..b37c43dc4 100644 --- a/backend/src/main/java/com/now/naaga/member/application/CreateMemberCommand.java +++ b/backend/src/main/java/com/now/naaga/member/application/dto/CreateMemberCommand.java @@ -1,4 +1,4 @@ -package com.now.naaga.member.application; +package com.now.naaga.member.application.dto; public record CreateMemberCommand(String email) { } diff --git a/backend/src/main/java/com/now/naaga/member/application/DeleteMemberCommand.java b/backend/src/main/java/com/now/naaga/member/application/dto/DeleteMemberCommand.java similarity index 54% rename from backend/src/main/java/com/now/naaga/member/application/DeleteMemberCommand.java rename to backend/src/main/java/com/now/naaga/member/application/dto/DeleteMemberCommand.java index 347ede966..8a43da3b1 100644 --- a/backend/src/main/java/com/now/naaga/member/application/DeleteMemberCommand.java +++ b/backend/src/main/java/com/now/naaga/member/application/dto/DeleteMemberCommand.java @@ -1,4 +1,4 @@ -package com.now.naaga.member.application; +package com.now.naaga.member.application.dto; public record DeleteMemberCommand(Long memberId) { } diff --git a/backend/src/main/java/com/now/naaga/player/application/PlayerService.java b/backend/src/main/java/com/now/naaga/player/application/PlayerService.java index 270c9ca49..b1c96dd24 100644 --- a/backend/src/main/java/com/now/naaga/player/application/PlayerService.java +++ b/backend/src/main/java/com/now/naaga/player/application/PlayerService.java @@ -1,20 +1,22 @@ package com.now.naaga.player.application; +import com.now.naaga.player.application.dto.AddScoreCommand; import com.now.naaga.player.application.dto.CreatePlayerCommand; import com.now.naaga.player.application.dto.DeletePlayerCommand; import com.now.naaga.player.domain.Player; import com.now.naaga.player.domain.Rank; import com.now.naaga.player.exception.PlayerException; -import com.now.naaga.player.exception.PlayerExceptionType; import com.now.naaga.player.persistence.repository.PlayerRepository; import com.now.naaga.player.presentation.dto.PlayerRequest; -import java.util.ArrayList; -import java.util.List; - import com.now.naaga.score.domain.Score; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; +import java.util.List; + +import static com.now.naaga.player.exception.PlayerExceptionType.PLAYER_NOT_FOUND; + @Transactional @Service public class PlayerService { @@ -28,7 +30,7 @@ public PlayerService(final PlayerRepository playerRepository) { @Transactional(readOnly = true) public Player findPlayerById(final Long id) { return playerRepository.findById(id) - .orElseThrow(() -> new PlayerException(PlayerExceptionType.PLAYER_NOT_FOUND)); + .orElseThrow(() -> new PlayerException(PLAYER_NOT_FOUND)); } @Transactional(readOnly = true) @@ -36,7 +38,7 @@ public Player findPlayerByMemberId(final Long memberId) { List playersByMemberId = playerRepository.findByMemberId(memberId); if (playersByMemberId.isEmpty()) { - throw new PlayerException(PlayerExceptionType.PLAYER_NOT_FOUND); + throw new PlayerException(PLAYER_NOT_FOUND); } return playersByMemberId.get(0); @@ -85,6 +87,14 @@ public Player create(final CreatePlayerCommand createPlayerCommand) { return playerRepository.save(player); } + public void addScore(final AddScoreCommand addScoreCommand) { + final Long playerId = addScoreCommand.playerId(); + final Score score = addScoreCommand.score(); + final Player player = findPlayerById(playerId); + + player.addScore(score); + } + public void deleteByMemberId(final DeletePlayerCommand deletePlayerCommand) { final List players = playerRepository.findByMemberId(deletePlayerCommand.memberId()); playerRepository.deleteAll(players); diff --git a/backend/src/main/java/com/now/naaga/player/application/dto/AddScoreCommand.java b/backend/src/main/java/com/now/naaga/player/application/dto/AddScoreCommand.java new file mode 100644 index 000000000..1b9215e21 --- /dev/null +++ b/backend/src/main/java/com/now/naaga/player/application/dto/AddScoreCommand.java @@ -0,0 +1,7 @@ +package com.now.naaga.player.application.dto; + +import com.now.naaga.score.domain.Score; + +public record AddScoreCommand(Long playerId, + Score score) { +} diff --git a/backend/src/main/java/com/now/naaga/player/domain/Player.java b/backend/src/main/java/com/now/naaga/player/domain/Player.java index 30050f4bc..c892c1a62 100644 --- a/backend/src/main/java/com/now/naaga/player/domain/Player.java +++ b/backend/src/main/java/com/now/naaga/player/domain/Player.java @@ -28,7 +28,7 @@ public class Player extends BaseEntity { private Score totalScore; @JoinColumn(name = "member_id") - @OneToOne + @OneToOne(fetch = FetchType.LAZY) private Member member; private boolean deleted = FALSE; diff --git a/backend/src/main/java/com/now/naaga/player/persistence/repository/PlayerRepository.java b/backend/src/main/java/com/now/naaga/player/persistence/repository/PlayerRepository.java index d79fc398f..305cc2fb4 100644 --- a/backend/src/main/java/com/now/naaga/player/persistence/repository/PlayerRepository.java +++ b/backend/src/main/java/com/now/naaga/player/persistence/repository/PlayerRepository.java @@ -3,8 +3,13 @@ import com.now.naaga.player.domain.Player; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; public interface PlayerRepository extends JpaRepository { List findByMemberId(final Long memberId); + + @Override + @Query("SELECT p FROM Player p JOIN FETCH p.member") + List findAll(); } diff --git a/backend/src/main/resources/application.yml b/backend/src/main/resources/application.yml index 2d27e4ef8..13f195ec9 100644 --- a/backend/src/main/resources/application.yml +++ b/backend/src/main/resources/application.yml @@ -55,6 +55,6 @@ spring: spring: config: - import: classpath:security/application-prod.yml + import: classpath:security/application-local.yml activate: - on-profile: prod + on-profile: local diff --git a/backend/src/test/java/com/now/naaga/common/builder/GameResultBuilder.java b/backend/src/test/java/com/now/naaga/common/builder/GameResultBuilder.java index edb826f9d..0b37718e4 100644 --- a/backend/src/test/java/com/now/naaga/common/builder/GameResultBuilder.java +++ b/backend/src/test/java/com/now/naaga/common/builder/GameResultBuilder.java @@ -3,9 +3,9 @@ import static com.now.naaga.game.domain.GameStatus.DONE; import com.now.naaga.game.domain.Game; -import com.now.naaga.game.domain.GameResult; -import com.now.naaga.game.domain.ResultType; -import com.now.naaga.game.repository.GameResultRepository; +import com.now.naaga.gameresult.domain.GameResult; +import com.now.naaga.gameresult.domain.ResultType; +import com.now.naaga.gameresult.repository.GameResultRepository; import com.now.naaga.score.domain.Score; import java.time.LocalDateTime; import java.util.Optional; diff --git a/backend/src/test/java/com/now/naaga/game/application/GameServiceTest.java b/backend/src/test/java/com/now/naaga/game/application/GameServiceTest.java index 9d891fd1c..03ae412a7 100644 --- a/backend/src/test/java/com/now/naaga/game/application/GameServiceTest.java +++ b/backend/src/test/java/com/now/naaga/game/application/GameServiceTest.java @@ -10,9 +10,12 @@ import com.now.naaga.game.application.dto.FindGameByStatusCommand; import com.now.naaga.game.domain.Game; import com.now.naaga.game.domain.GameRecord; -import com.now.naaga.game.domain.GameResult; +import com.now.naaga.game.exception.GameNotFinishedException; +import com.now.naaga.gameresult.domain.GameResult; import com.now.naaga.game.domain.Statistic; import com.now.naaga.game.exception.GameException; +import com.now.naaga.gameresult.exception.GameResultException; +import com.now.naaga.gameresult.exception.GameResultExceptionType; import com.now.naaga.place.domain.Place; import com.now.naaga.player.domain.Player; import com.now.naaga.player.presentation.dto.PlayerRequest; @@ -28,12 +31,14 @@ import java.util.List; import static com.now.naaga.common.fixture.PositionFixture.*; +import static com.now.naaga.game.domain.EndType.ARRIVED; import static com.now.naaga.game.domain.EndType.GIVE_UP; import static com.now.naaga.game.domain.GameStatus.DONE; import static com.now.naaga.game.domain.GameStatus.IN_PROGRESS; -import static com.now.naaga.game.domain.ResultType.FAIL; -import static com.now.naaga.game.domain.ResultType.SUCCESS; +import static com.now.naaga.gameresult.domain.ResultType.FAIL; +import static com.now.naaga.gameresult.domain.ResultType.SUCCESS; import static com.now.naaga.game.exception.GameExceptionType.*; +import static com.now.naaga.gameresult.exception.GameResultExceptionType.*; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.SoftAssertions.assertSoftly; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -103,8 +108,8 @@ class GameServiceTest { .build(); //then - GameException gameException = assertThrows(GameException.class, () -> gameService.findGameResultByGameId(game.getId())); - assertThat(gameException.exceptionType()).isEqualTo(GAME_RESULT_NOT_EXIST); + GameResultException gameResultException = assertThrows(GameResultException.class, () -> gameService.findGameResultByGameId(game.getId())); + assertThat(gameResultException.exceptionType()).isEqualTo(GAME_RESULT_NOT_EXIST); } @Test @@ -318,7 +323,7 @@ class GameServiceTest { } @Test - void 종료요청이_들어오면_게임결과를_저장한다() { + void 게임을_포기하면_게임을_종료한다() { // given final Player player = playerBuilder.init() .build(); @@ -340,12 +345,16 @@ class GameServiceTest { gameService.endGame(new EndGameCommand(player.getId(), GIVE_UP, 잠실_루터회관_정문_좌표, game.getId())); // then - final GameResult expected = gameService.findGameResultByGameId(game.getId()); - assertThat(expected.getGame().getId()).isEqualTo(game.getId()); + final FindGameByIdCommand findGameByIdCommand = new FindGameByIdCommand(game.getId(), player.getId()); + final Game expected = gameService.findGameById(findGameByIdCommand); + assertSoftly(softAssertions -> { + softAssertions.assertThat(expected.getEndTime()).isNotNull(); + softAssertions.assertThat(expected.getGameStatus()).isEqualTo(DONE); + }); } @Test - void 종료요청이_들어왔을때_GameNotArrivalException이_발생해도_롤백되지않고_게임결과를_저장한다() { + void 목적지_주변에서_도착_도전하면_게임을_종료한다() { // given final Player player = playerBuilder.init() .build(); @@ -364,15 +373,49 @@ class GameServiceTest { .build(); // when - gameService.endGame(new EndGameCommand(player.getId(), GIVE_UP, 역삼역_좌표, game.getId())); + gameService.endGame(new EndGameCommand(player.getId(), ARRIVED, 잠실_루터회관_정문_좌표, game.getId())); // then - final GameResult expected = gameService.findGameResultByGameId(game.getId()); - assertThat(expected.getGame().getId()).isEqualTo(game.getId()); + final FindGameByIdCommand findGameByIdCommand = new FindGameByIdCommand(game.getId(), player.getId()); + final Game expected = gameService.findGameById(findGameByIdCommand); + assertSoftly(softAssertions -> { + softAssertions.assertThat(expected.getEndTime()).isNotNull(); + softAssertions.assertThat(expected.getGameStatus()).isEqualTo(DONE); + }); + } + + @Test + void 종료요청이_들어왔을때_GameNotArrivalException이_발생해도_롤백되지않고_게임결과를_저장한다() { + // given + final Player player = playerBuilder.init() + .build(); + + final Place destination = placeBuilder.init() + .position(잠실_루터회관_정문_좌표) + .build(); + + final Game game = gameBuilder.init() + .place(destination) + .player(player) + .gameStatus(IN_PROGRESS) + .startTime(LocalDateTime.of(2023, Month.AUGUST, 13, 15, 30, 0)) + .startPosition(잠실역_교보문고_좌표) + .remainingAttempts(3) + .build(); + + // when & then + final EndGameCommand endGameCommand = new EndGameCommand(player.getId(), ARRIVED, 역삼역_좌표, game.getId()); + final FindGameByIdCommand findGameByIdCommand = new FindGameByIdCommand(game.getId(), player.getId()); + assertSoftly(softAssertions -> { + softAssertions.assertThatThrownBy(() -> gameService.endGame(endGameCommand)).isInstanceOf(GameNotFinishedException.class); + final Game expected = gameService.findGameById(findGameByIdCommand); + softAssertions.assertThat(expected.getGameStatus()).isEqualTo(IN_PROGRESS); + softAssertions.assertThat(expected.getEndTime()).isNull(); + }); } @Test - void 게임임생성_요청이_들어오면_게임을_저장하고_반환한다() { + void 게임생성_요청이_들어오면_게임을_저장하고_반환한다() { // given final Player player = playerBuilder.init() .build(); @@ -389,7 +432,7 @@ class GameServiceTest { } @Test - void 게임임생성_요청이_들어왔을때_진행중인_게임이_있다면_예외를_발생시킨다() { + void 게임생성_요청이_들어왔을때_진행중인_게임이_있다면_예외를_발생시킨다() { // given final Player player = playerBuilder.init() .build(); @@ -421,10 +464,6 @@ class GameServiceTest { final Player player = playerBuilder.init() .build(); - final Place destination = placeBuilder.init() - .position(역삼역_좌표) - .build(); - // when GameException gameException = assertThrows(GameException.class, () -> gameService.createGame(new CreateGameCommand(player.getId(), 잠실역_교보문고_좌표))); diff --git a/backend/src/test/java/com/now/naaga/game/application/HintServiceTest.java b/backend/src/test/java/com/now/naaga/game/application/HintServiceTest.java index 7c27b0c3e..f511504c8 100644 --- a/backend/src/test/java/com/now/naaga/game/application/HintServiceTest.java +++ b/backend/src/test/java/com/now/naaga/game/application/HintServiceTest.java @@ -17,6 +17,7 @@ import com.now.naaga.game.domain.Game; import com.now.naaga.game.domain.Hint; import com.now.naaga.game.exception.GameException; +import com.now.naaga.member.domain.Member; import com.now.naaga.place.domain.Place; import java.time.LocalDateTime; import org.junit.jupiter.api.DisplayNameGeneration; @@ -26,10 +27,13 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.jdbc.Sql; +import org.springframework.transaction.annotation.Transactional; @SuppressWarnings("NonAsciiCharacters") @DisplayNameGeneration(ReplaceUnderscores.class) @Sql("/truncate.sql") + +@ActiveProfiles("test") @SpringBootTest class HintServiceTest { @@ -42,6 +46,7 @@ class HintServiceTest { @Autowired private PlaceBuilder placeBuilder; + @Transactional @Test void 힌트를_생성한다() { // given @@ -61,6 +66,9 @@ class HintServiceTest { // when final Hint actual = hintService.createHint(createHintCommand); + place.getRegisteredPlayer().getMember(); + game.getPlayer().getMember(); + // then final Hint expected = new Hint(서울_좌표, Direction.SOUTH, diff --git a/backend/src/test/java/com/now/naaga/game/domain/GameTest.java b/backend/src/test/java/com/now/naaga/game/domain/GameTest.java index 9853fb5f5..e89146dc5 100644 --- a/backend/src/test/java/com/now/naaga/game/domain/GameTest.java +++ b/backend/src/test/java/com/now/naaga/game/domain/GameTest.java @@ -1,29 +1,11 @@ package com.now.naaga.game.domain; -import static com.now.naaga.common.fixture.PlaceFixture.PLACE; -import static com.now.naaga.common.fixture.PlayerFixture.PLAYER; -import static com.now.naaga.common.fixture.PositionFixture.GS25_방이도곡점_좌표; -import static com.now.naaga.common.fixture.PositionFixture.던킨도너츠_올림픽공원점_좌표; -import static com.now.naaga.common.fixture.PositionFixture.잠실_루터회관_정문_근처_좌표; -import static com.now.naaga.common.fixture.PositionFixture.잠실_루터회관_정문_좌표; -import static com.now.naaga.game.domain.EndType.ARRIVED; -import static com.now.naaga.game.domain.EndType.GIVE_UP; -import static com.now.naaga.game.domain.Game.MAX_ATTEMPT_COUNT; -import static com.now.naaga.game.domain.GameStatus.DONE; -import static com.now.naaga.game.domain.GameStatus.IN_PROGRESS; -import static com.now.naaga.game.domain.ResultType.FAIL; -import static com.now.naaga.game.domain.ResultType.SUCCESS; -import static com.now.naaga.game.exception.GameExceptionType.ALREADY_DONE; -import static com.now.naaga.game.exception.GameExceptionType.NOT_ARRIVED; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; - import com.now.naaga.game.exception.GameException; +import com.now.naaga.game.exception.GameNotFinishedException; import com.now.naaga.place.domain.Place; import com.now.naaga.place.domain.Position; import com.now.naaga.player.domain.Player; -import java.time.LocalDateTime; -import java.util.ArrayList; +import org.assertj.core.api.SoftAssertions; import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Test; @@ -31,6 +13,20 @@ import org.junit.jupiter.params.provider.ValueSource; import org.springframework.test.context.ActiveProfiles; +import java.time.LocalDateTime; +import java.util.ArrayList; + +import static com.now.naaga.common.fixture.PlaceFixture.PLACE; +import static com.now.naaga.common.fixture.PlayerFixture.PLAYER; +import static com.now.naaga.common.fixture.PositionFixture.*; +import static com.now.naaga.game.domain.EndType.ARRIVED; +import static com.now.naaga.game.domain.EndType.GIVE_UP; +import static com.now.naaga.game.domain.Game.MAX_ATTEMPT_COUNT; +import static com.now.naaga.game.domain.Game.MAX_HINT_COUNT; +import static com.now.naaga.game.domain.GameStatus.DONE; +import static com.now.naaga.game.domain.GameStatus.IN_PROGRESS; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + @ActiveProfiles("test") @SuppressWarnings("NonAsciiCharacters") @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) @@ -38,59 +34,60 @@ class GameTest { private final Player player = PLAYER(); - private Game game; - @Test - void 게임을_포기한_경우_진행중인_게임은_실패로_종료한다() { + void 게임을_포기한_경우_진행중인_게임은_종료한다() { // given - Place destination = PLACE(잠실_루터회관_정문_좌표, player); - Position startPosition = 던킨도너츠_올림픽공원점_좌표; - Position currentPosition = GS25_방이도곡점_좌표; - game = new Game(player, destination, startPosition); + final Place destination = PLACE(잠실_루터회관_정문_좌표, player); + final Position startPosition = 던킨도너츠_올림픽공원점_좌표; + final Position currentPosition = GS25_방이도곡점_좌표; + final Game game = new Game(player, destination, startPosition); //when - ResultType gameResult = game.endGame(GIVE_UP, currentPosition); + game.endGame(currentPosition, GIVE_UP); // then - assertThat(game.getGameStatus()).isEqualTo(DONE); - assertThat(game.getRemainingAttempts()).isEqualTo(MAX_ATTEMPT_COUNT); - assertThat(gameResult).isEqualTo(FAIL); + SoftAssertions.assertSoftly(softAssertions -> { + softAssertions.assertThat(game.getGameStatus()).isEqualTo(DONE); + softAssertions.assertThat(game.getRemainingAttempts()).isEqualTo(MAX_ATTEMPT_COUNT); + }); } @ParameterizedTest @ValueSource(ints = {1, 2, 3, 4, 5}) - void 제한_횟수_내에_목적지에_도착한_경우_진행중인_게임은_성공으로_종료한다(int remainingAttempts) { + void 제한_횟수_내에_목적지에_도착한_경우_진행중인_게임은_성공으로_종료한다() { // given - Place destination = PLACE(잠실_루터회관_정문_좌표, player); - Position startPosition = 던킨도너츠_올림픽공원점_좌표; - Position currentPosition = 잠실_루터회관_정문_근처_좌표; - game = new Game(IN_PROGRESS, player, destination, startPosition, remainingAttempts, new ArrayList<>(), LocalDateTime.now(), null); + final Place destination = PLACE(잠실_루터회관_정문_좌표, player); + final Position startPosition = 던킨도너츠_올림픽공원점_좌표; + final Position currentPosition = 잠실_루터회관_정문_근처_좌표; + final Game game = new Game(player, destination, startPosition); //when - ResultType actual = game.endGame(ARRIVED, currentPosition); + game.endGame(currentPosition, ARRIVED); // then - assertThat(game.getGameStatus()).isEqualTo(DONE); - assertThat(game.getRemainingAttempts()).isEqualTo(remainingAttempts - 1); - assertThat(actual).isEqualTo(SUCCESS); + SoftAssertions.assertSoftly(softAssertions -> { + softAssertions.assertThat(game.getGameStatus()).isEqualTo(DONE); + softAssertions.assertThat(game.getRemainingAttempts()).isEqualTo(MAX_ATTEMPT_COUNT - 1); + }); } @Test void 마지막_시도에_도착하지_못한_경우_진행중인_게임은_실패로_종료한다() { // given - int remainingAttempts = 1; - Place destination = PLACE(잠실_루터회관_정문_좌표, player); - Position startPosition = 던킨도너츠_올림픽공원점_좌표; - Position currentPosition = GS25_방이도곡점_좌표; - game = new Game(IN_PROGRESS, player, destination, startPosition, remainingAttempts, new ArrayList<>(), LocalDateTime.now(), null); + final int remainingAttempts = 1; + final Place destination = PLACE(잠실_루터회관_정문_좌표, player); + final Position startPosition = 던킨도너츠_올림픽공원점_좌표; + final Position currentPosition = GS25_방이도곡점_좌표; + final Game game = new Game(IN_PROGRESS, player, destination, startPosition, remainingAttempts, new ArrayList<>(), LocalDateTime.now(), null); //when - ResultType actual = game.endGame(ARRIVED, currentPosition); + game.endGame(currentPosition, ARRIVED); // then - assertThat(game.getGameStatus()).isEqualTo(DONE); - assertThat(game.getRemainingAttempts()).isEqualTo(remainingAttempts - 1); - assertThat(actual).isEqualTo(FAIL); + SoftAssertions.assertSoftly(softAssertions -> { + softAssertions.assertThat(game.getGameStatus()).isEqualTo(DONE); + softAssertions.assertThat(game.getRemainingAttempts()).isEqualTo(0); + }); } //예외 발생 사례 @@ -98,27 +95,25 @@ class GameTest { @ValueSource(ints = {0, 1, 2, 3, 4, 5}) void 게임이_종료된_경우_예외가_발생한다(int remainingAttempts) { // given - Place destination = PLACE(잠실_루터회관_정문_좌표, player); - Position startPosition = 던킨도너츠_올림픽공원점_좌표; - Position currentPosition = 잠실_루터회관_정문_근처_좌표; - game = new Game(DONE, player, destination, startPosition, remainingAttempts, new ArrayList<>(), LocalDateTime.now(), null); - - //then - GameException gameException = assertThrows(GameException.class, () -> game.endGame(ARRIVED, currentPosition)); - assertThat(gameException.exceptionType()).isEqualTo(ALREADY_DONE); + final Place destination = PLACE(잠실_루터회관_정문_좌표, player); + final Position startPosition = 던킨도너츠_올림픽공원점_좌표; + final Position currentPosition = 잠실_루터회관_정문_근처_좌표; + final Game game = new Game(DONE, player, destination, startPosition, remainingAttempts, new ArrayList<>(), LocalDateTime.now(), null); + + //when & then + assertThatThrownBy(() -> game.endGame(currentPosition, ARRIVED)).isInstanceOf(GameException.class); } @ParameterizedTest @ValueSource(ints = {2, 3, 4, 5}) void 마지막_시도가_아닌_제한_횟수_내에_목적지에_도착하지_못한_경우_예외가_발생한다(int remainingAttempts) { // given - Place destination = PLACE(잠실_루터회관_정문_좌표, player); - Position startPosition = 던킨도너츠_올림픽공원점_좌표; - Position currentPosition = GS25_방이도곡점_좌표; - game = new Game(IN_PROGRESS, player, destination, startPosition, remainingAttempts, new ArrayList<>(), LocalDateTime.now(), null); - - //then - GameException gameException = assertThrows(GameException.class, () -> game.endGame(ARRIVED, currentPosition)); - assertThat(gameException.exceptionType()).isEqualTo(NOT_ARRIVED); + final Place destination = PLACE(잠실_루터회관_정문_좌표, player); + final Position startPosition = 던킨도너츠_올림픽공원점_좌표; + final Position currentPosition = GS25_방이도곡점_좌표; + final Game game = new Game(IN_PROGRESS, player, destination, startPosition, remainingAttempts, new ArrayList<>(), LocalDateTime.now(), null); + + //when & then + assertThatThrownBy(() -> game.endGame(currentPosition, ARRIVED)).isInstanceOf(GameNotFinishedException.class); } } diff --git a/backend/src/test/java/com/now/naaga/game/domain/GameScorePolicyTest.java b/backend/src/test/java/com/now/naaga/game/domain/ResultScorePolicyTest.java similarity index 95% rename from backend/src/test/java/com/now/naaga/game/domain/GameScorePolicyTest.java rename to backend/src/test/java/com/now/naaga/game/domain/ResultScorePolicyTest.java index b1d80943f..beacce10f 100644 --- a/backend/src/test/java/com/now/naaga/game/domain/GameScorePolicyTest.java +++ b/backend/src/test/java/com/now/naaga/game/domain/ResultScorePolicyTest.java @@ -1,7 +1,7 @@ package com.now.naaga.game.domain; -import com.now.naaga.game.domain.gamescore.GameScorePolicy; -import com.now.naaga.game.domain.gamescore.SuccessGameScorePolicy; +import com.now.naaga.gameresult.domain.gamescore.ResultScorePolicy; +import com.now.naaga.gameresult.domain.gamescore.SuccessResultScorePolicy; import com.now.naaga.player.domain.Player; import com.now.naaga.score.domain.Score; import org.junit.jupiter.api.DisplayNameGeneration; @@ -21,10 +21,10 @@ @ActiveProfiles("test") @SuppressWarnings("NonAsciiCharacters") @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) -class GameScorePolicyTest { +class ResultScorePolicyTest { private final Player player = PLAYER(); - private final GameScorePolicy gameScorer = new SuccessGameScorePolicy(); + private final ResultScorePolicy gameScorer = new SuccessResultScorePolicy(); @Test void 다른_조건이_같고_거리가_멀수록_점수가_높다() { diff --git a/backend/src/test/java/com/now/naaga/game/domain/StatisticTest.java b/backend/src/test/java/com/now/naaga/game/domain/StatisticTest.java index a1ce8c9f5..3865c809c 100644 --- a/backend/src/test/java/com/now/naaga/game/domain/StatisticTest.java +++ b/backend/src/test/java/com/now/naaga/game/domain/StatisticTest.java @@ -1,5 +1,6 @@ package com.now.naaga.game.domain; +import com.now.naaga.gameresult.domain.GameResult; import com.now.naaga.place.domain.Place; import com.now.naaga.place.domain.Position; import com.now.naaga.player.domain.Player; @@ -20,7 +21,7 @@ import static com.now.naaga.common.fixture.PositionFixture.던킨도너츠_올림픽공원점_좌표; import static com.now.naaga.common.fixture.PositionFixture.잠실_루터회관_정문_좌표; import static com.now.naaga.game.domain.GameStatus.DONE; -import static com.now.naaga.game.domain.ResultType.SUCCESS; +import static com.now.naaga.gameresult.domain.ResultType.SUCCESS; import static org.assertj.core.api.SoftAssertions.assertSoftly; @ActiveProfiles("test") diff --git a/backend/src/test/java/com/now/naaga/game/domain/gamescore/GameScoreCalculatorTest.java b/backend/src/test/java/com/now/naaga/game/domain/gamescore/ResultScoreCalculatorTest.java similarity index 78% rename from backend/src/test/java/com/now/naaga/game/domain/gamescore/GameScoreCalculatorTest.java rename to backend/src/test/java/com/now/naaga/game/domain/gamescore/ResultScoreCalculatorTest.java index 1c634c54f..45be29a23 100644 --- a/backend/src/test/java/com/now/naaga/game/domain/gamescore/GameScoreCalculatorTest.java +++ b/backend/src/test/java/com/now/naaga/game/domain/gamescore/ResultScoreCalculatorTest.java @@ -3,13 +3,14 @@ import static com.now.naaga.common.fixture.PlaceFixture.PLACE; import static com.now.naaga.common.fixture.PlayerFixture.PLAYER; import static com.now.naaga.common.fixture.PositionFixture.서울_좌표; -import static com.now.naaga.game.domain.ResultType.FAIL; -import static com.now.naaga.game.domain.ResultType.SUCCESS; +import static com.now.naaga.gameresult.domain.ResultType.FAIL; +import static com.now.naaga.gameresult.domain.ResultType.SUCCESS; import static org.assertj.core.api.Assertions.assertThat; import com.now.naaga.game.domain.Game; import com.now.naaga.game.domain.GameStatus; -import com.now.naaga.game.domain.ResultType; +import com.now.naaga.gameresult.domain.ResultType; +import com.now.naaga.gameresult.domain.gamescore.ResultScoreCalculator; import com.now.naaga.score.domain.Score; import java.time.LocalDateTime; import java.util.Collections; @@ -22,10 +23,10 @@ @SuppressWarnings("NonAsciiCharacters") @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) @SpringBootTest -class GameScoreCalculatorTest { +class ResultScoreCalculatorTest { @Autowired - GameScoreCalculator gameScoreCalculator; + ResultScoreCalculator resultScoreCalculator; @Test void 게임결과가_성공일_때_점수를_얻는다() { @@ -36,7 +37,7 @@ class GameScoreCalculatorTest { LocalDateTime.now().minusHours(1), LocalDateTime.now()); //when - final Score actual = gameScoreCalculator.calculate(game, resultType); + final Score actual = resultScoreCalculator.calculate(game, resultType); //then assertThat(actual.getValue()).isGreaterThan(0); @@ -51,7 +52,7 @@ class GameScoreCalculatorTest { LocalDateTime.now().minusHours(1), LocalDateTime.now()); //when - final Score actual = gameScoreCalculator.calculate(game, resultType); + final Score actual = resultScoreCalculator.calculate(game, resultType); //then assertThat(actual.getValue()).isZero(); diff --git a/backend/src/test/java/com/now/naaga/game/presentation/GameControllerTest.java b/backend/src/test/java/com/now/naaga/game/presentation/GameControllerTest.java index a68b60fae..69744849a 100644 --- a/backend/src/test/java/com/now/naaga/game/presentation/GameControllerTest.java +++ b/backend/src/test/java/com/now/naaga/game/presentation/GameControllerTest.java @@ -10,6 +10,7 @@ import com.now.naaga.game.presentation.dto.*; import com.now.naaga.game.repository.GameRepository; import com.now.naaga.game.repository.HintRepository; +import com.now.naaga.gameresult.domain.GameResult; import com.now.naaga.member.domain.Member; import com.now.naaga.place.domain.Place; import com.now.naaga.place.presentation.dto.CoordinateResponse; @@ -39,8 +40,8 @@ import static com.now.naaga.game.domain.Game.MAX_ATTEMPT_COUNT; import static com.now.naaga.game.domain.GameStatus.DONE; import static com.now.naaga.game.domain.GameStatus.IN_PROGRESS; -import static com.now.naaga.game.domain.ResultType.FAIL; -import static com.now.naaga.game.domain.ResultType.SUCCESS; +import static com.now.naaga.gameresult.domain.ResultType.FAIL; +import static com.now.naaga.gameresult.domain.ResultType.SUCCESS; import static com.now.naaga.game.exception.GameExceptionType.*; import static org.assertj.core.api.SoftAssertions.assertSoftly; @@ -184,10 +185,6 @@ protected void setUp() { @Test void 게임_생성_요청시_주변에_추천_장소가_없다면_예외가_발생한다() { // given - final Place destination = placeBuilder.init() - .position(잠실_루터회관_정문_좌표) - .build(); - final Player player = playerBuilder.init() .build(); diff --git a/backend/src/test/java/com/now/naaga/gameresult/application/GameResultServiceTest.java b/backend/src/test/java/com/now/naaga/gameresult/application/GameResultServiceTest.java new file mode 100644 index 000000000..21cf335fe --- /dev/null +++ b/backend/src/test/java/com/now/naaga/gameresult/application/GameResultServiceTest.java @@ -0,0 +1,91 @@ +package com.now.naaga.gameresult.application; + +import com.now.naaga.common.builder.GameBuilder; +import com.now.naaga.common.builder.GameResultBuilder; +import com.now.naaga.common.builder.PlaceBuilder; +import com.now.naaga.common.builder.PlayerBuilder; +import com.now.naaga.game.application.dto.CreateGameResultCommand; +import com.now.naaga.game.domain.Game; +import com.now.naaga.game.exception.GameException; +import com.now.naaga.gameresult.domain.GameResult; +import com.now.naaga.gameresult.exception.GameResultException; +import com.now.naaga.gameresult.repository.GameResultRepository; +import com.now.naaga.place.domain.Position; +import com.now.naaga.player.domain.Player; +import com.now.naaga.score.domain.Score; +import org.assertj.core.api.SoftAssertions; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.jdbc.Sql; + +import java.time.LocalDateTime; + +import static com.now.naaga.game.domain.EndType.ARRIVED; +import static com.now.naaga.game.domain.GameStatus.DONE; +import static com.now.naaga.game.domain.GameStatus.IN_PROGRESS; +import static com.now.naaga.gameresult.domain.ResultType.SUCCESS; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +@Sql("/truncate.sql") +@ActiveProfiles("test") +@SpringBootTest +class GameResultServiceTest { + + @Autowired + private GameResultRepository gameResultRepository; + + @Autowired + private GameResultService gameResultService; + + @Autowired + private GameBuilder gameBuilder; + + @Autowired + private GameResultBuilder gameResultBuilder; + + @Autowired + private PlayerBuilder playerBuilder; + + @Autowired + private PlaceBuilder placeBuilder; + + @Test + void 사용자의_위치가_도착_범위_안이고_엔트타입이_도착이면_게임_결과를_성공으로_생성_후_저장하고_플레이어의_점수를_올린다() { + //given + final Player player = playerBuilder.init().build(); + final Score beforeScore = player.getTotalScore(); + final Game game = gameBuilder.init().player(player).gameStatus(DONE).endTime(LocalDateTime.now().plusMinutes(30)).build(); + final Position position = game.getPlace().getPosition(); + final CreateGameResultCommand createGameResultCommand = new CreateGameResultCommand(player, game, position, ARRIVED); + + //when + gameResultService.createGameResult(createGameResultCommand); + + //then + final GameResult gameResult = gameResultRepository.findByGameId(game.getId()).get(0); + final Score totalScore = gameResult.getGame().getPlayer().getTotalScore(); + final Score expectedScore = beforeScore.plus(gameResult.getScore()); + SoftAssertions.assertSoftly(softAssertions -> { + softAssertions.assertThat(gameResult.getResultType()).isEqualTo(SUCCESS); + softAssertions.assertThat(totalScore).isEqualTo(expectedScore); + }); + } + + @Test + void 종료되지_않은_게임의_게임결과를_만들려하면_예외를_발생한다() { + //given + final Player player = playerBuilder.init().build(); + final Game game = gameBuilder.init().player(player).gameStatus(IN_PROGRESS).build(); + final Position position = game.getPlace().getPosition(); + final CreateGameResultCommand createGameResultCommand = new CreateGameResultCommand(player, game, position, ARRIVED); + + //when & then + assertThatThrownBy(() -> gameResultService.createGameResult(createGameResultCommand)) + .isInstanceOf(GameException.class); + } +} diff --git a/backend/src/test/java/com/now/naaga/player/application/PlayerServiceTest.java b/backend/src/test/java/com/now/naaga/player/application/PlayerServiceTest.java index ea6a8f1a1..593aa8b2b 100644 --- a/backend/src/test/java/com/now/naaga/player/application/PlayerServiceTest.java +++ b/backend/src/test/java/com/now/naaga/player/application/PlayerServiceTest.java @@ -1,9 +1,12 @@ package com.now.naaga.player.application; +import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.SoftAssertions.assertSoftly; +import com.now.naaga.common.builder.PlayerBuilder; import com.now.naaga.member.domain.Member; import com.now.naaga.member.persistence.repository.MemberRepository; +import com.now.naaga.player.application.dto.AddScoreCommand; import com.now.naaga.player.domain.Player; import com.now.naaga.player.domain.Rank; import com.now.naaga.player.persistence.repository.PlayerRepository; @@ -11,6 +14,8 @@ import com.now.naaga.score.domain.Score; import java.util.ArrayList; import java.util.List; + +import org.assertj.core.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.DisplayNameGenerator; @@ -36,6 +41,9 @@ class PlayerServiceTest { @Autowired private MemberRepository memberRepository; + @Autowired + private PlayerBuilder playerBuilder; + private List playerList = new ArrayList<>(); @BeforeEach @@ -78,4 +86,20 @@ void setUp() { softly.assertThat(rank.getPercentage()).isEqualTo(33); }); } + + @Test + void 플레이어의_점수를_추가한다() { + // given + final Player player = playerBuilder.init().build(); + final Score beforeScore = player.getTotalScore(); + final Score addedScore = new Score(10); + final AddScoreCommand addScoreCommand = new AddScoreCommand(player.getId(), addedScore); + + // when + playerService.addScore(addScoreCommand); + + // then + final Player afterPlayer = playerRepository.findById(player.getId()).get(); + assertThat(afterPlayer.getTotalScore()).isEqualTo(beforeScore.plus(addedScore)); + } }