diff --git a/docs/README.md b/docs/README.md index e69de29bb2..5ff90a903b 100644 --- a/docs/README.md +++ b/docs/README.md @@ -0,0 +1,44 @@ +# [ 구현할 기능 목록 ] + +1. 게임 시작 문구 출력 + - "숫자 야구 게임을 시작합니다." 출력 + + +2. 1~9 의 서로 다른 숫자 3개 생성 (컴퓨터숫자 생성) + + +3. 사용자로부터 숫자 입력 받기 + + +4. 입력 받은 숫자 Validation 진행 + - (1) 1부터 9 까지의 (2) 서로 다른 (3) 숫자 (4) 3개여야 함 + - 예외 처리 : 0, 숫자가 아닌 값, 서로 다른 숫자 3개가 아닌 경우 + + +5. 입력 받은 숫자와 컴퓨터 숫자를 비교 + - 낫싱 여부, 볼 개수, 스트라이크 개수 계산 + + +6. 비교한 값을 전달 받아 결과 문자열 생성 + - (ex) 낫싱, 1볼, 2스트라이크, 1볼 1스트라이크 + + +7. 결과 문자열 출력 + + +8. 게임 종료 여부 체크 + - 3개의 숫자를 모두 맞추면 (3 스트라이크) true, 아니면 false + - true 인 경우, 아래 내용 출력 + - "3개의 숫자를 모두 맞히셨습니다! 게임 종료" + - "게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요." + - false 인 경우 + - 3번 (사용자로부터 숫자 입력받기) 으로 돌아가서 값이 true일 때까지 반복 + + +9. 8번이 true인 경우, 8번에 대한 입력 값 Validation 진행 + - 1 또는 2 가 아닌 값이면 예외 처리 + + +10. 입력 값에 따라 다시 시작, 완전 종료 진행 + - 1 -> 다시 시작 (2번 부터 반복) + - 2 -> 완전 종료 (프로그램 종료) \ No newline at end of file diff --git a/src/main/java/baseball/Application.java b/src/main/java/baseball/Application.java index dd95a34214..5bfaba7f88 100644 --- a/src/main/java/baseball/Application.java +++ b/src/main/java/baseball/Application.java @@ -1,7 +1,12 @@ package baseball; +import baseball.controller.MainController; +import camp.nextstep.edu.missionutils.Console; + public class Application { public static void main(String[] args) { - // TODO: 프로그램 구현 + MainController mainController = MainController.getInstance(); + mainController.run(); + Console.close(); } } diff --git a/src/main/java/baseball/controller/GamePlayController.java b/src/main/java/baseball/controller/GamePlayController.java new file mode 100644 index 0000000000..1568f9163e --- /dev/null +++ b/src/main/java/baseball/controller/GamePlayController.java @@ -0,0 +1,57 @@ +package baseball.controller; + +import baseball.dto.RoundResultDto; +import baseball.model.UserNumber; +import baseball.service.GameManager; +import baseball.view.InputView; +import baseball.view.OutputView; + +import java.util.List; + +public class GamePlayController { + private static GamePlayController instance = new GamePlayController(InputView.getInstance(), OutputView.getInstance()); + private final InputView inputView; + private final OutputView outputView; + private GameManager gameManager; + + public GamePlayController(InputView inputView, OutputView outputView) { + this.inputView = inputView; + this.outputView = outputView; + } + + public static GamePlayController getInstance() { + return instance; + } + + public boolean playRound() { + outputView.printStart(); + initializeGameManager(); + boolean needsNextRound = true; + while (needsNextRound) { + UserNumber userNumber = readUserNumber(); + needsNextRound = playRound(userNumber); + printRoundResult(); + } + return needsNextRound; + } + + private void initializeGameManager() { + gameManager = GameManager.create(); + } + + private UserNumber readUserNumber() { + List numbers = inputView.readUserNumber(); + return UserNumber.from(numbers); + } + + private boolean playRound(UserNumber userNumber) { + boolean needsNextRound; + needsNextRound = gameManager.playRound(userNumber); + return needsNextRound; + } + + private void printRoundResult() { + RoundResultDto resultDto = gameManager.createResultDto(); + outputView.printResult(resultDto.isNothing(), resultDto.getBallCount(), resultDto.getStrikeCount()); + } +} \ No newline at end of file diff --git a/src/main/java/baseball/controller/GameRestartController.java b/src/main/java/baseball/controller/GameRestartController.java new file mode 100644 index 0000000000..d056351284 --- /dev/null +++ b/src/main/java/baseball/controller/GameRestartController.java @@ -0,0 +1,31 @@ +package baseball.controller; + +import baseball.model.PlayAgainDecision; +import baseball.view.InputView; +import baseball.view.OutputView; + +public class GameRestartController { + public static GameRestartController instance = new GameRestartController(InputView.getInstance(), OutputView.getInstance()); + private final InputView inputView; + private final OutputView outputView; + + public GameRestartController(InputView inputView, OutputView outputView) { + this.inputView = inputView; + this.outputView = outputView; + } + + public static GameRestartController getInstance() { + return instance; + } + + public boolean wantsRestart() { + outputView.printEnd(); + PlayAgainDecision playAgainDecision = readPlayAgainInput(); + return playAgainDecision.isAgain(); + } + + private PlayAgainDecision readPlayAgainInput() { + int input = inputView.readPlayAgainInput(); + return PlayAgainDecision.of(input); + } +} \ No newline at end of file diff --git a/src/main/java/baseball/controller/MainController.java b/src/main/java/baseball/controller/MainController.java new file mode 100644 index 0000000000..ab24ed2513 --- /dev/null +++ b/src/main/java/baseball/controller/MainController.java @@ -0,0 +1,25 @@ +package baseball.controller; + +public class MainController { + public static MainController instance = new MainController(GamePlayController.getInstance(), GameRestartController.getInstance()); + private final GamePlayController gamePlayController; + private final GameRestartController gameRestartController; + + private MainController(GamePlayController gamePlayController, GameRestartController gameRestartController) { + this.gamePlayController = gamePlayController; + this.gameRestartController = gameRestartController; + } + + public static MainController getInstance() { + return instance; + } + + public void run() { + boolean continuePlaying = true; + while (continuePlaying) { + if (!gamePlayController.playRound()) { + continuePlaying = gameRestartController.wantsRestart(); + } + } + } +} \ No newline at end of file diff --git a/src/main/java/baseball/dto/RoundResultDto.java b/src/main/java/baseball/dto/RoundResultDto.java new file mode 100644 index 0000000000..147c26d001 --- /dev/null +++ b/src/main/java/baseball/dto/RoundResultDto.java @@ -0,0 +1,32 @@ +package baseball.dto; + +import baseball.model.RoundResult; + +public class RoundResultDto { + public boolean isNothing; + public int ballCount; + public int strikeCount; + + private RoundResultDto() { + } + + public static RoundResultDto from(RoundResult roundResult) { + RoundResultDto dto = new RoundResultDto(); + dto.isNothing = roundResult.isNothing(); + dto.ballCount = roundResult.provideBallCount(); + dto.strikeCount = roundResult.provideStrikeCount(); + return dto; + } + + public boolean isNothing() { + return isNothing; + } + + public int getBallCount() { + return ballCount; + } + + public int getStrikeCount() { + return strikeCount; + } +} \ No newline at end of file diff --git a/src/main/java/baseball/exception/ErrorMessage.java b/src/main/java/baseball/exception/ErrorMessage.java new file mode 100644 index 0000000000..004e2a020f --- /dev/null +++ b/src/main/java/baseball/exception/ErrorMessage.java @@ -0,0 +1,19 @@ +package baseball.exception; + +public enum ErrorMessage { + ERROR_CAPTION("[ERROR] "), + INVALID_USER_NUMBER_INPUT_FORMAT("숫자를 입력해 주세요."), + INVALID_USER_NUMBER_CONTAINS_ZERO("0이 아닌 숫자 3개를 입력해주세요."), + DUPLICATED_USER_NUMBER("서로 다른 숫자 3개를 입력해주세요."), + INVALID_PLAY_AGAIN("1 또는 2를 입력해주세요."); + + private final String message; + + ErrorMessage(String message) { + this.message = message; + } + + public String getMessage() { + return ERROR_CAPTION.message + message; + } +} diff --git a/src/main/java/baseball/model/ComputerNumber.java b/src/main/java/baseball/model/ComputerNumber.java new file mode 100644 index 0000000000..4ededa9013 --- /dev/null +++ b/src/main/java/baseball/model/ComputerNumber.java @@ -0,0 +1,26 @@ +package baseball.model; + +import baseball.utils.NumbersGenerator; + +import java.util.List; + +public class ComputerNumber { + private final List numbers; + + private ComputerNumber(List numbers) { + this.numbers = numbers; + } + + public static ComputerNumber create() { + List numbers = NumbersGenerator.generate(); + return new ComputerNumber(numbers); + } + + public boolean containsNumber(int number) { + return numbers.contains(number); + } + + public int findNumberByPosition(int position) { + return numbers.get(position); + } +} \ No newline at end of file diff --git a/src/main/java/baseball/model/PlayAgainDecision.java b/src/main/java/baseball/model/PlayAgainDecision.java new file mode 100644 index 0000000000..2c42ab58ed --- /dev/null +++ b/src/main/java/baseball/model/PlayAgainDecision.java @@ -0,0 +1,39 @@ +package baseball.model; + +import static baseball.exception.ErrorMessage.INVALID_PLAY_AGAIN; +import static baseball.model.PlayAgainDecision.PlayAgainConstants.NO; +import static baseball.model.PlayAgainDecision.PlayAgainConstants.YES; + +public class PlayAgainDecision { + private final int value; + + private PlayAgainDecision(int input) { + value = input; + } + + public static PlayAgainDecision of(int input) { + validate(input); + return new PlayAgainDecision(input); + } + + private static void validate(int input) { + if ((input != YES.value) && (input != NO.value)) { + throw new IllegalArgumentException(INVALID_PLAY_AGAIN.getMessage()); + } + } + + public boolean isAgain() { + return value == YES.value; + } + + enum PlayAgainConstants { + YES(1), + NO(2); + + private final int value; + + PlayAgainConstants(int value) { + this.value = value; + } + } +} diff --git a/src/main/java/baseball/model/RoundResult.java b/src/main/java/baseball/model/RoundResult.java new file mode 100644 index 0000000000..dabdeaec09 --- /dev/null +++ b/src/main/java/baseball/model/RoundResult.java @@ -0,0 +1,48 @@ +package baseball.model; + +import java.util.stream.IntStream; + +import static baseball.utils.Constants.NUMBERS_SIZE; +import static baseball.utils.Constants.START_INDEX; + +public class RoundResult { + private int ballCount = 0; + private int strikeCount = 0; + + private RoundResult(ComputerNumber computerNumber, UserNumber userNumber) { + processRound(computerNumber, userNumber); + } + + public static RoundResult create(ComputerNumber computerNumber, UserNumber userNumber) { + return new RoundResult(computerNumber, userNumber); + } + + private void processRound(ComputerNumber computerNumber, UserNumber userNumber) { + for (int position = START_INDEX; position < NUMBERS_SIZE; position++) { + int number = userNumber.findNumberByPosition(position); + if (computerNumber.containsNumber(number)) { + if (computerNumber.findNumberByPosition(position) == number) { + strikeCount++; + continue; + } + ballCount++; + } + } + } + + public boolean isNothing() { + return ballCount == 0 && strikeCount == 0; + } + + public boolean needsNextRound() { + return strikeCount != 3; + } + + public int provideBallCount() { + return ballCount; + } + + public int provideStrikeCount() { + return strikeCount; + } +} \ No newline at end of file diff --git a/src/main/java/baseball/model/UserNumber.java b/src/main/java/baseball/model/UserNumber.java new file mode 100644 index 0000000000..57cd7b2207 --- /dev/null +++ b/src/main/java/baseball/model/UserNumber.java @@ -0,0 +1,25 @@ +package baseball.model; + +import java.util.List; + +import static baseball.utils.validator.UserNumberValidator.*; + + +public class UserNumber { + private final List numbers; + + private UserNumber(List numbers) { + this.numbers = numbers; + } + + public static UserNumber from(List numbers) { + validateNonZero(numbers); + validateDuplicate(numbers); + validateSize(numbers); + return new UserNumber(numbers); + } + + public int findNumberByPosition(int position) { + return numbers.get(position); + } +} \ No newline at end of file diff --git a/src/main/java/baseball/service/GameManager.java b/src/main/java/baseball/service/GameManager.java new file mode 100644 index 0000000000..6323dad37a --- /dev/null +++ b/src/main/java/baseball/service/GameManager.java @@ -0,0 +1,29 @@ +package baseball.service; + +import baseball.dto.RoundResultDto; +import baseball.model.ComputerNumber; +import baseball.model.RoundResult; +import baseball.model.UserNumber; + +public class GameManager { + private final ComputerNumber computerNumber; + private RoundResult roundResult; + + private GameManager(ComputerNumber computerNumber) { + this.computerNumber = computerNumber; + } + + public static GameManager create() { + ComputerNumber computerNumber = ComputerNumber.create(); + return new GameManager(computerNumber); + } + + public boolean playRound(UserNumber userNumber) { + roundResult = RoundResult.create(computerNumber, userNumber); + return roundResult.needsNextRound(); + } + + public RoundResultDto createResultDto() { + return RoundResultDto.from(roundResult); + } +} \ No newline at end of file diff --git a/src/main/java/baseball/utils/Constants.java b/src/main/java/baseball/utils/Constants.java new file mode 100644 index 0000000000..d2c0530a34 --- /dev/null +++ b/src/main/java/baseball/utils/Constants.java @@ -0,0 +1,6 @@ +package baseball.utils; + +public class Constants { + public static final int START_INDEX = 0; + public static final int NUMBERS_SIZE = 3; +} diff --git a/src/main/java/baseball/utils/NumbersGenerator.java b/src/main/java/baseball/utils/NumbersGenerator.java new file mode 100644 index 0000000000..6a51e3542d --- /dev/null +++ b/src/main/java/baseball/utils/NumbersGenerator.java @@ -0,0 +1,19 @@ +package baseball.utils; + +import camp.nextstep.edu.missionutils.Randoms; + +import java.util.ArrayList; +import java.util.List; + +public class NumbersGenerator { + public static List generate() { + List numbers = new ArrayList<>(); + while (numbers.size() != 3) { + int number = Randoms.pickNumberInRange(1, 9); + if (!numbers.contains(number)) { + numbers.add(number); + } + } + return numbers; + } +} diff --git a/src/main/java/baseball/utils/validator/PlayAgainInputValidator.java b/src/main/java/baseball/utils/validator/PlayAgainInputValidator.java new file mode 100644 index 0000000000..d8e0ef914c --- /dev/null +++ b/src/main/java/baseball/utils/validator/PlayAgainInputValidator.java @@ -0,0 +1,13 @@ +package baseball.utils.validator; + +import static baseball.exception.ErrorMessage.INVALID_PLAY_AGAIN; + +public class PlayAgainInputValidator { + public static int safeParseInt(String input) { + try { + return Integer.parseInt(input); + } catch (NumberFormatException e) { + throw new IllegalArgumentException(INVALID_PLAY_AGAIN.getMessage()); + } + } +} diff --git a/src/main/java/baseball/utils/validator/UserNumberValidator.java b/src/main/java/baseball/utils/validator/UserNumberValidator.java new file mode 100644 index 0000000000..8181dc2336 --- /dev/null +++ b/src/main/java/baseball/utils/validator/UserNumberValidator.java @@ -0,0 +1,48 @@ +package baseball.utils.validator; + +import baseball.utils.Constants; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import static baseball.exception.ErrorMessage.*; + +public class UserNumberValidator { + private static final int INVALID_NUMBER = 0; + + public static void validateNumeric(String input) { + try { + Integer.parseInt(input); + } catch (NumberFormatException e) { + throw new IllegalArgumentException(INVALID_USER_NUMBER_INPUT_FORMAT.getMessage()); + } + } + + public static List convertToIntegerList(String input) { + return input.chars() + .map(Character::getNumericValue) + .boxed() + .collect(Collectors.toList()); + } + + public static void validateNonZero(List numbers) { + if (numbers.contains(INVALID_NUMBER)) { + throw new IllegalArgumentException(INVALID_USER_NUMBER_CONTAINS_ZERO.getMessage()); + } + } + + public static void validateDuplicate(List numbers) { + Set set = new HashSet<>(numbers); + if (set.size() != numbers.size()) { + throw new IllegalArgumentException(DUPLICATED_USER_NUMBER.getMessage()); + } + } + + public static void validateSize(List numbers) { + if (numbers.size() != Constants.NUMBERS_SIZE) { + throw new IllegalArgumentException(DUPLICATED_USER_NUMBER.getMessage()); + } + } +} diff --git a/src/main/java/baseball/view/InputView.java b/src/main/java/baseball/view/InputView.java new file mode 100644 index 0000000000..fe5335cfad --- /dev/null +++ b/src/main/java/baseball/view/InputView.java @@ -0,0 +1,33 @@ +package baseball.view; + +import baseball.utils.validator.PlayAgainInputValidator; +import baseball.utils.validator.UserNumberValidator; +import camp.nextstep.edu.missionutils.Console; + +import java.util.List; + +public class InputView { + public static InputView instance = new InputView(); + private static final String ASK_USER_NUMBER_MESSAGE = "숫자를 입력해주세요 : "; + private static final String ASK_PLAY_AGAIN_MESSAGE = "게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요."; + + private InputView() { + } + + public static InputView getInstance() { + return instance; + } + + public List readUserNumber() { + System.out.print(ASK_USER_NUMBER_MESSAGE); + String input = Console.readLine(); + UserNumberValidator.validateNumeric(input); + return UserNumberValidator.convertToIntegerList(input); + } + + public int readPlayAgainInput() { + System.out.println(ASK_PLAY_AGAIN_MESSAGE); + String input = Console.readLine(); + return PlayAgainInputValidator.safeParseInt(input); + } +} diff --git a/src/main/java/baseball/view/OutputView.java b/src/main/java/baseball/view/OutputView.java new file mode 100644 index 0000000000..1102a1af1b --- /dev/null +++ b/src/main/java/baseball/view/OutputView.java @@ -0,0 +1,48 @@ +package baseball.view; + +public class OutputView { + public static OutputView instance = new OutputView(); + private static final String START_MESSAGE = "숫자 야구 게임을 시작합니다."; + private static final String NOTHING_MESSAGE = "낫싱"; + private static final String BALL_FORMAT = "%d볼 "; + private static final String STRIKE_FORMAT = "%d스트라이크"; + private static final String END_MESSAGE = "3개의 숫자를 모두 맞히셨습니다! 게임 종료"; + + private OutputView() { + } + + public static OutputView getInstance() { + return instance; + } + + public void printStart() { + System.out.println(START_MESSAGE); + } + + public void printResult(boolean isNothing, int ballCount, int strikeCount) { + if (isNothing) { + printNothing(); + return; + } + printBallAndStrike(ballCount, strikeCount); + } + + private void printNothing() { + System.out.println(NOTHING_MESSAGE); + } + + private void printBallAndStrike(int ballCount, int strikeCount) { + StringBuilder resultMessage = new StringBuilder(); + if (ballCount != 0) { + resultMessage.append(String.format(BALL_FORMAT, ballCount)); + } + if (strikeCount != 0) { + resultMessage.append(String.format(STRIKE_FORMAT, strikeCount)); + } + System.out.println(resultMessage); + } + + public void printEnd() { + System.out.println(END_MESSAGE); + } +} diff --git a/src/test/java/baseball/ApplicationTest.java b/src/test/java/baseball/ApplicationTest.java index 3fa29fa67b..c65d069d28 100644 --- a/src/test/java/baseball/ApplicationTest.java +++ b/src/test/java/baseball/ApplicationTest.java @@ -32,4 +32,5 @@ class ApplicationTest extends NsTest { public void runMain() { Application.main(new String[]{}); } + } diff --git a/src/test/java/baseball/model/ComputerNumberTest.java b/src/test/java/baseball/model/ComputerNumberTest.java new file mode 100644 index 0000000000..9d0e1a316a --- /dev/null +++ b/src/test/java/baseball/model/ComputerNumberTest.java @@ -0,0 +1,21 @@ +package baseball.model; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class ComputerNumberTest { + @DisplayName("1 이상 9 이하의 숫자 3개가 생성된다.") + @Test + void create() { + // given + ComputerNumber computerNumber = ComputerNumber.create(); + + // when, then + assertThat(computerNumber.findNumberByPosition(0)).isBetween(1, 9); + assertThat(computerNumber.findNumberByPosition(1)).isBetween(1, 9); + assertThat(computerNumber.findNumberByPosition(2)).isBetween(1, 9); + } + +} \ No newline at end of file diff --git a/src/test/java/baseball/model/PlayAgainDecisionTest.java b/src/test/java/baseball/model/PlayAgainDecisionTest.java new file mode 100644 index 0000000000..9c3b16bda3 --- /dev/null +++ b/src/test/java/baseball/model/PlayAgainDecisionTest.java @@ -0,0 +1,23 @@ +package baseball.model; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class PlayAgainDecisionTest { + @ParameterizedTest(name = "[{index}] {0} 을 넣으면 정상 생성된다") + @ValueSource(ints = {1, 2}) + void create(int element) { + PlayAgainDecision playAgainDecision = PlayAgainDecision.of(element); + assertThat(playAgainDecision).isNotNull(); + } + + @ParameterizedTest(name = "[{index}] {0} 을 넣으면 예외가 발생한다.") + @ValueSource(ints = {-1, 0, 3, 5, 100}) + void validateInput_ex(int element) { + assertThatThrownBy(() -> PlayAgainDecision.of(element)) + .isInstanceOf(IllegalArgumentException.class); + } +} \ No newline at end of file diff --git a/src/test/java/baseball/model/RoundResultTest.java b/src/test/java/baseball/model/RoundResultTest.java new file mode 100644 index 0000000000..a3445fb22a --- /dev/null +++ b/src/test/java/baseball/model/RoundResultTest.java @@ -0,0 +1,149 @@ +package baseball.model; + + +import camp.nextstep.edu.missionutils.Randoms; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +class RoundResultTest { + @DisplayName("두 숫자를 비교하여 결과를 출력한다 - 낫싱") + @Test + void create() { + try (MockedStatic randoms = Mockito.mockStatic(Randoms.class)) { + randoms.when(() -> Randoms.pickNumberInRange(1, 9)).thenReturn(1).thenReturn(2).thenReturn(3); + + ComputerNumber computerNumber = ComputerNumber.create(); + UserNumber userNumber = UserNumber.from(List.of(4, 5, 6)); + RoundResult roundResult = RoundResult.create(computerNumber, userNumber); + assertThat(roundResult.isNothing()).isTrue(); + assertThat(roundResult.provideBallCount()).isEqualTo(0); + assertThat(roundResult.provideStrikeCount()).isEqualTo(0); + } + } + + @DisplayName("입력 받은 숫자와 컴퓨터 숫자 비교 - 숫자 1개가 같고 다른 자리에 있으면 - 1볼") + @Test + void generateResult2() { + try (MockedStatic randoms = Mockito.mockStatic(Randoms.class)) { + randoms.when(() -> Randoms.pickNumberInRange(1, 9)).thenReturn(1).thenReturn(2).thenReturn(3); + + ComputerNumber computerNumber = ComputerNumber.create(); + UserNumber userNumber = UserNumber.from(List.of(4, 5, 1)); + RoundResult roundResult = RoundResult.create(computerNumber, userNumber); + assertThat(roundResult.isNothing()).isFalse(); + assertThat(roundResult.provideBallCount()).isEqualTo(1); + assertThat(roundResult.provideStrikeCount()).isEqualTo(0); + } + } + + @DisplayName("입력 받은 숫자와 컴퓨터 숫자 비교 - 2볼") + @Test + void generateResult3() { + try (MockedStatic randoms = Mockito.mockStatic(Randoms.class)) { + randoms.when(() -> Randoms.pickNumberInRange(1, 9)).thenReturn(1).thenReturn(2).thenReturn(3); + + ComputerNumber computerNumber = ComputerNumber.create(); + UserNumber userNumber = UserNumber.from(List.of(3, 5, 1)); + RoundResult roundResult = RoundResult.create(computerNumber, userNumber); + assertThat(roundResult.isNothing()).isFalse(); + assertThat(roundResult.provideBallCount()).isEqualTo(2); + assertThat(roundResult.provideStrikeCount()).isEqualTo(0); + } + } + + @DisplayName("입력 받은 숫자와 컴퓨터 숫자 비교 - 3볼") + @Test + void generateResult4() { + try (MockedStatic randoms = Mockito.mockStatic(Randoms.class)) { + randoms.when(() -> Randoms.pickNumberInRange(1, 9)).thenReturn(1).thenReturn(2).thenReturn(3); + + ComputerNumber computerNumber = ComputerNumber.create(); + UserNumber userNumber = UserNumber.from(List.of(2, 3, 1)); + RoundResult roundResult = RoundResult.create(computerNumber, userNumber); + assertThat(roundResult.isNothing()).isFalse(); + assertThat(roundResult.provideBallCount()).isEqualTo(3); + assertThat(roundResult.provideStrikeCount()).isEqualTo(0); + } + } + + @DisplayName("입력 받은 숫자와 컴퓨터 숫자 비교 - 1스트라이크") + @Test + void generateResult5() { + try (MockedStatic randoms = Mockito.mockStatic(Randoms.class)) { + randoms.when(() -> Randoms.pickNumberInRange(1, 9)).thenReturn(1).thenReturn(2).thenReturn(3); + + ComputerNumber computerNumber = ComputerNumber.create(); + UserNumber userNumber = UserNumber.from(List.of(1, 4, 5)); + RoundResult roundResult = RoundResult.create(computerNumber, userNumber); + assertThat(roundResult.isNothing()).isFalse(); + assertThat(roundResult.provideBallCount()).isEqualTo(0); + assertThat(roundResult.provideStrikeCount()).isEqualTo(1); + } + } + + @DisplayName("입력 받은 숫자와 컴퓨터 숫자 비교 - 2스트라이크") + @Test + void generateResult6() { + try (MockedStatic randoms = Mockito.mockStatic(Randoms.class)) { + randoms.when(() -> Randoms.pickNumberInRange(1, 9)).thenReturn(1).thenReturn(2).thenReturn(3); + + ComputerNumber computerNumber = ComputerNumber.create(); + UserNumber userNumber = UserNumber.from(List.of(1, 2, 5)); + RoundResult roundResult = RoundResult.create(computerNumber, userNumber); + assertThat(roundResult.isNothing()).isFalse(); + assertThat(roundResult.provideBallCount()).isEqualTo(0); + assertThat(roundResult.provideStrikeCount()).isEqualTo(2); + } + } + + @DisplayName("입력 받은 숫자와 컴퓨터 숫자 비교 - 3스트라이크") + @Test + void generateResult7() { + try (MockedStatic randoms = Mockito.mockStatic(Randoms.class)) { + randoms.when(() -> Randoms.pickNumberInRange(1, 9)).thenReturn(1).thenReturn(2).thenReturn(3); + + ComputerNumber computerNumber = ComputerNumber.create(); + UserNumber userNumber = UserNumber.from(List.of(1, 4, 5)); + RoundResult roundResult = RoundResult.create(computerNumber, userNumber); + assertThat(roundResult.isNothing()).isFalse(); + assertThat(roundResult.provideBallCount()).isEqualTo(0); + assertThat(roundResult.provideStrikeCount()).isEqualTo(1); + } + } + + @DisplayName("입력 받은 숫자와 컴퓨터 숫자 비교 - 1볼 1스트라이크") + @Test + void generateResult8() { + try (MockedStatic randoms = Mockito.mockStatic(Randoms.class)) { + randoms.when(() -> Randoms.pickNumberInRange(1, 9)).thenReturn(1).thenReturn(2).thenReturn(3); + + ComputerNumber computerNumber = ComputerNumber.create(); + UserNumber userNumber = UserNumber.from(List.of(1, 4, 2)); + RoundResult roundResult = RoundResult.create(computerNumber, userNumber); + assertThat(roundResult.isNothing()).isFalse(); + assertThat(roundResult.provideBallCount()).isEqualTo(1); + assertThat(roundResult.provideStrikeCount()).isEqualTo(1); + } + } + + @DisplayName("입력 받은 숫자와 컴퓨터 숫자 비교 - 2볼 1스트라이크") + @Test + void generateResult9() { + try (MockedStatic randoms = Mockito.mockStatic(Randoms.class)) { + randoms.when(() -> Randoms.pickNumberInRange(1, 9)).thenReturn(1).thenReturn(2).thenReturn(3); + + ComputerNumber computerNumber = ComputerNumber.create(); + UserNumber userNumber = UserNumber.from(List.of(1, 3, 2)); + RoundResult roundResult = RoundResult.create(computerNumber, userNumber); + assertThat(roundResult.isNothing()).isFalse(); + assertThat(roundResult.provideBallCount()).isEqualTo(2); + assertThat(roundResult.provideStrikeCount()).isEqualTo(1); + } + } +} \ No newline at end of file diff --git a/src/test/java/baseball/model/UserNumberTest.java b/src/test/java/baseball/model/UserNumberTest.java new file mode 100644 index 0000000000..c4f3639210 --- /dev/null +++ b/src/test/java/baseball/model/UserNumberTest.java @@ -0,0 +1,37 @@ +package baseball.model; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.List; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class UserNumberTest { + static Stream generateData() { + return Stream.of( + Arguments.of(List.of(0, 1, 2)), + Arguments.of(List.of(1, 1, 2)), + Arguments.of(List.of(1, 2, 3, 4)) + ); + } + + @DisplayName("입력 받은 숫자가 1~9의 서로 다른 숫자 3개인 경우 정상 처리 된다.") + @Test + void validatePlayerNumber_o() { + UserNumber userNumber = UserNumber.from(List.of(1, 2, 3)); + assertThat(userNumber).isNotNull(); + } + + @ParameterizedTest(name = "[{index}] {0} 입력 시 예외가 발생한다.") + @MethodSource("generateData") + void validatePlayerNumber_ex(List numbers) { + assertThatThrownBy(() -> UserNumber.from(numbers)) + .isInstanceOf(IllegalArgumentException.class); + } +} \ No newline at end of file diff --git a/src/test/java/baseball/service/GameResultServiceTest.java b/src/test/java/baseball/service/GameResultServiceTest.java new file mode 100644 index 0000000000..fc6140078d --- /dev/null +++ b/src/test/java/baseball/service/GameResultServiceTest.java @@ -0,0 +1,14 @@ +package baseball.service; + + +class GameResultServiceTest { + + //computerNumber, userNumber 비교하여 나오는 결과 테스트 시 사용 가능 +// static Stream generateData() { +// return Stream.of( +// Arguments.of(Arrays.asList(1, 2, 3), Arrays.asList(1, 3, 2), 0), +// Arguments.of(Arrays.asList(1, 2, 3), Arrays.asList(4, 5, 6), 1) +// ); +// } + +} \ No newline at end of file