Тестирование ввода с помощью junit

Итак, я разработал эту очень простую игру TicTacToe. Я хочу протестировать метод, приведенный ниже:

public class Board {

    private Scanner scan = new Scanner(System.in);

    public int inputBoardSize() {
        while (flag) {
            System.out.print("Enter the number of grids you want to play with:");
            try {
                boardSize = Integer.parseInt(scan.next());
                if (boardSize < 3 || boardSize > 10) {
                    System.out.println("Please choose a board size between 3 and 10");
                    continue;
                }
                flag = false;
                break;
            } catch (NumberFormatException e) {
                e.getMessage();
                System.out.println("Please enter a number");
                continue;
            }

        }
        printBoard(boardSize);
        return boardSize;
    }

Но я новичок в модульном тестировании и мне нужна небольшая помощь. Я не могу понять, как проверить два условия

  1. NumberFormatException
  2. Когда ввод не находится между 3 и 10.

Мой класс тестирования для второго условия выглядит примерно так:

public class BoardTest extends TestCase {

    @Test
    public void test() {
        Board board = new Board();

        String input = "2";
        InputStream in = new ByteArrayInputStream(input.getBytes());
        System.setIn(in);

    }
}

Я не могу понять, что делать дальше.

Как вы проверяете 3-е условие: входные является 3 и 10?

Timothy Truckle 08.04.2018 13:27

Вам нужно использовать то, что называется Внедрение зависимости. Предоставьте экземпляр Scanner вашему методу. В производстве вы можете использовать System.in, тогда как при тестировании вы можете использовать другой InputStream, который будет воспроизводить ваш тестовый пример.

flakes 08.04.2018 13:29

Я использовал InputStream. Примерно так: @Test public void test () {Board board = new Board (); Строка input = "2"; InputStream in = новый ByteArrayInputStream (input.getBytes ()); System.setIn (вход); }

perpetualcoder 08.04.2018 13:57

Итак, что мешает вам создавать копии этого метода тестирования, в которых вы меняете "2" на "11" или "not a number"?

Timothy Truckle 08.04.2018 14:03
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
4
470
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Добавьте следующие конструкторы:

public class Board {

    private Scanner;

    public Board() {
        this(System.in);
    }

    public Board(InputStream in) {
        scan = new Scanner(in);
    }

}

Затем вы можете предоставить InputStream извне при тестировании класса.

Ответ принят как подходящий

Вы можете выделить логику проверки в отдельный метод, а затем протестировать этот метод. Это устраняет необходимость взаимодействовать или вводить объект Scanner. Извлеченный код будет напоминать

public int inputBoardSize() {
    while (flag) {
        System.out.print("Enter the number of grids you want to play with:");
        validateBoardSize(scan.next());
    }
    printBoard(boardSize);
    return boardSize;
}

protected void validateBoardSize(String input) {

    try {
        boardSize = Integer.parseInt(input);
        if (boardSize < 3 || boardSize > 10) {
            System.out.println("Please choose a board size between 3 and 10");
        }
        else {
            flag = false;
        }
    } 
    catch (NumberFormatException e) {
        e.getMessage();
        System.out.println("Please enter a number");
    }
}

Вот некоторые тестовые примеры JUnit для проверки метода validateBoardSize:

public class BoardTest {

    private static final String OUT_OUT_BOUNDS_ERROR_MESSAGE = "Please choose a board size between 3 and 10";
    private static final String NFE_ERROR_MESSAGE = "Please enter a number";
    private final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
    private Board board;

    @Before
    public void setUp() {
        System.setOut(new PrintStream(outContent));
        board = new Board();
    }

    @Test
    public void setBoardSizeOf2EnsureErrorMessageDisplayed() {
        board.validateBoardSize("2");
        assertOutOfBoundsErrorMessageDisplayed();
    }

    private void assertOutOfBoundsErrorMessageDisplayed() {
        assertEquals(OUT_OUT_BOUNDS_ERROR_MESSAGE, outContent.toString().trim());
    }

    @Test
    public void setBoardSizeOf3EnsureNoErrorMessageDisplayed() {
        board.validateBoardSize("3");
        assertNoErrorMessageDisplayed();
    }

    private void assertNoErrorMessageDisplayed() {
        assertEquals("", outContent.toString().trim());
    }

    @Test
    public void setBoardSizeOf4EnsureNoErrorMessageDisplayed() {
        board.validateBoardSize("4");
        assertNoErrorMessageDisplayed();
    }

    @Test
    public void setBoardSizeOf9EnsureNoErrorMessageDisplayed() {
        board.validateBoardSize("9");
        assertNoErrorMessageDisplayed();
    }

    @Test
    public void setBoardSizeOf10EnsureNoErrorMessageDisplayed() {
        board.validateBoardSize("10");
        assertNoErrorMessageDisplayed();
    }

    @Test
    public void setBoardSizeOf11EnsureErrorMessageDisplayed() {
        board.validateBoardSize("11");
        assertOutOfBoundsErrorMessageDisplayed();
    }

    @Test
    public void setBoardSizeWithInvalidNumberEnsureInvalidNumberMessageDisplayed() {
        board.validateBoardSize("blah");
        assertInvalidNumberMessageDisplayed();
    }

    private void assertInvalidNumberMessageDisplayed() {
        assertEquals(NFE_ERROR_MESSAGE, outContent.toString().trim());
    }
}

Обратите внимание, что поскольку ваша программа обозначает ошибки через сообщения, отправленные через стандартный вывод (в отличие от выдачи исключений), тесты должны перехватывать выводимое сообщение, отправленное на стандартный вывод, и сравнивать строку, чтобы увидеть, что говорится в сообщении. Следовательно, в setUp() для OutputStream для стандартного вывода устанавливается экземпляр OutputStream, строковое значение которого можно сравнить с помощью методов тестирования: System.setOut(new PrintStream(outContent)). Чтобы проверить вывод, вы можете просто извлечь строковое значение OutputStream: outContent.toString().trim(). Обратите внимание, что trim() используется для удаления завершающего символа (ов) новой строки, поскольку println будет включать их в сообщение об ошибке. Новые строки чувствительны к ОС, поэтому их удаление значительно упрощает сравнение строки.

Для получения дополнительной информации см. Тест JUnit для System.out.println().

Большое спасибо! Это очень помогло понять, как это работает.

perpetualcoder 08.04.2018 18:34

Поэтому я использую System.err вместо System.out. И модульный тест не работает org.junit.ComparisonFailure: ожидалось: <[Пожалуйста, введите число]>, но было: <[]>. Есть ли другой способ проверить операторы system.err?

perpetualcoder 12.04.2018 13:18

Есть способ проверить стандартную ошибку вместо стандартного вывода. В методе setUp() замените System.setOut(new PrintStream(outContent)) на System.setErr(new PrintStream(outContent)). Это позволит вам захватить и протестировать вывод, напечатанный на стандартную ошибку. Для получения дополнительной информации о том, как это работает, см. Документация по System.setErr.

Justin Albano 12.04.2018 13:25

Другие вопросы по теме