使用junit测试输入

时间:2018-04-08 11:22:51

标签: java unit-testing junit mockito

所以我开发了这个非常简单的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之间时。
  3. 第二个条件的测试类是这样的:

    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);
    
        }
    }
    

    我无法弄清楚下一步该做什么。

2 个答案:

答案 0 :(得分:1)

您可以将验证逻辑提取到单独的方法中,然后测试该方法。这消除了交互或注入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");
    }
}

使用validateBoardSize方法的一些JUnit测试用例将是:

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))。要测试输出,您只需提取OutputStreamoutContent.toString().trim()的字符串值即可。请注意,trim()用于删除尾随的换行符,因为println会将它们包含在错误消息中。换行符对操作系统非常敏感,因此删除它们会使字符串的比较更加直接。

有关详细信息,请参阅JUnit test for System.out.println()

答案 1 :(得分:0)

添加以下构造函数:

public class Board {

    private Scanner;

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

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

}

然后,您可以在测试课程时从外部提供InputStream