You can extract the validation logic into a separate method and then test that method. This removes the need to interact or inject a Scanner
object. The extracted code would resemble
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");
}
}
Some JUnit test cases to exercise the validateBoardSize
method would be:
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());
}
}
Note that since your program denotes errors through messages sent through standard output (as opposed to throwing exceptions), the tests must intercept the output message sent to standard output and do a string compare to see what the message says. Hence, within setUp()
, the OutputStream
for standard output is set to an OutputStream
instance whose string value can be compared against by the test methods: System.setOut(new PrintStream(outContent))
. To test the output, you can just extract the string value of the OutputStream
: outContent.toString().trim()
. Note that trim()
is used to remove the trailing newline character(s), since println
will include them in the error message. Newlines are OS-sensitive, so removing them makes comparing the string much more straightforward.
For more information, see JUnit test for System.out.println()
.