I'm attempting to make a Tic-Tac-Toe class and unit test all of the methods. Right now, my class file looks as follows:
public class TicTacToe {
public static final Character PLAYER_1 = 'X';
public static final Character PLAYER_2 = 'O';
public static final Integer BOARD_SIZE = 3;
private char[][] board;
private char currentPlayer;
public TicTacToe() {
board = new char[BOARD_SIZE][BOARD_SIZE];
initializeBoard();
currentPlayer = PLAYER_1;
}
public void initializeBoard() {
for(char[] row: board) {
Arrays.fill(row, '-');
}
}
public void printBoard() {
for(int i = 0; i < BOARD_SIZE; i ) {
for(int j = 0; j < BOARD_SIZE; j ) {
System.out.print(board[i][j]);
if(j == BOARD_SIZE - 1) {
System.out.println();
}
else {
System.out.print(" ,");
}
}
}
}
public boolean makeMove(int x, int y) {
if(x >= BOARD_SIZE || y >= BOARD_SIZE || x < 0 || y < 0 || board[x][y] != '-') {
return false;
}
board[x][y] = currentPlayer;
currentPlayer = currentPlayer == PLAYER_1 ? PLAYER_2 : PLAYER_1;
return true;
}
// more methods are below
}
If I wanted to test that printBoard() works when the entire board is full, how would I do that without making calls to makeMove() or making all of my class variables public?
Currently, my testing file looks as follows:
import org.junit.*;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.io.*;
import static org.junit.jupiter.api.Assertions.*;
class TicTacToeTest {
private final PrintStream standardOut = System.out;
private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream();
@BeforeEach
public void setUp() {
System.setOut(new PrintStream(outputStreamCaptor));
}
@org.junit.jupiter.api.Test
@AfterEach
public void tearDown() {
System.setOut(standardOut);
}
@Test
void initializeBoard() {
}
@Test
void printBoard() {
TicTacToe game = new TicTacToe();
game.printBoard();
assertEquals("- ,- ,-\r\n- ,- ,-\r\n- ,- ,-", outputStreamCaptor.toString()
.trim());
// I want to test that a full board works for printBoard() right here.
}
// more testing methods below
}
I saw something about using @Jailbreak in Manifold, but I couldn't get that working. If it helps anyone, I'm using IntelliJ. Thank you for any help ya'll!
CodePudding user response:
Three optional options (there are more):
- Create a second constructor of TicTacToe where you can pass into a prefilled board
public TicTacToe(char[][] board)
- Add an extra method
public void loadBoard(char[][] board)
. - Use reflection to fill the board variable. (bad option because this can results in another state)
- Add a package-private constructor and let both classes reside in the same package.
- Create package-private setBoard method and access it in the arrange-part of your code.
You can also do something with partical mocking but I think thats also not a good option in this situation.
Another good option is to create a separate class for printing out the board:
public class BoardPrinter {
public BoardPrinter() {}
public printBoard(char[][] board} {
// print the board
}
}