This question comes a bit as continuation of the following topic (you don’t need to read it, though). It’s just a game of Tetris I’m implementing with TDD.
So here is the problem: I have a set of Acceptance tests. I have defined the following test in one of them:
[TestMethod]
public void I_Can_Query_Any_Piece_Of_The_Board_For_A_Color() {
StandardTetris tetris = new StandardTetris();
for (int y = 0; y < tetris.BoardSize.Height; ++y) {
for (int x = 0; x < tetris.BoardSize.Width; ++x) {
Color color = tetris.GetColorAt(x, y);
Assert.IsTrue(
color == Color.Cyan ||
color == Color.Blue ||
color == Color.Orange ||
color == Color.Yellow ||
color == Color.Green ||
color == Color.Violet ||
color == Color.Red
);
}
}
}
which made me change a method I had on StandardTetris
public Color GetColorAt(int x, int y)
{
return Color.Black;
}
to
public Color GetColorAt(int x, int y)
{
return Color.Orange;
}
The next test I’d like to do on was setting a couple of pixels to some colors, and then checking if they are indeed with that color in the positions I put them(although, now that I think of it, that would not be acceptance tests).
How can I do that?
StandardTetris doesn’t provide any kind of setter for the board pieces(not it is supposed to do it!) and I don’t want to have any other constructor than the default one. How can I mock it, then?
This is the current code on StandardTetris:
public class StandardTetris
{
private static readonly int BOARD_WIDTH = 10;
private static readonly int BOARD_HEIGHT = 22;
private Size boardSize = new Size(BOARD_WIDTH, BOARD_HEIGHT);
public Size BoardSize { get { return boardSize; } }
public Color GetColorAt(int x, int y)
{
return Color.Orange;
}
}
and by using your suggestions, I made the following test:
[TestMethod]
public void Set_A_Blue_2x2_Square_On_Origin_And_Query_It_Sucessfully() {
Board board = new Board();
board.SetColorAt(0, 0, Color.Blue);
board.SetColorAt(0, 1, Color.Blue);
board.SetColorAt(1, 0, Color.Blue);
board.SetColorAt(1, 1, Color.Blue);
Tetris tetris = new Tetris(board);
Assert.AreEqual(Color.Blue, tetris.GetColorAt(0, 0));
Assert.AreEqual(Color.Blue, tetris.GetColorAt(1, 0));
Assert.AreEqual(Color.Blue, tetris.GetColorAt(0, 1));
Assert.AreEqual(Color.Blue, tetris.GetColorAt(1, 1));
}
I see two options:
Create a second constructor where you can pass in pre-constructed information.
Create a test class
TestStandardTetristhat inherits fromStandardTetriswhere the only difference isTestStandardTetrishas the constructor for taking the pre-constructed information.Your tests are saying to you that you need a way to set the state, and you’re saying you don’t want the state to change, hence the lack of a setter, so the only place left to set the state is the constructor.
The first option opens it up to the game’s main API.
The second only opens it up to tests, and any future person who works with your API who decides to inherit from
StandardTetris, it will also allow you test the functionality of StandardTetris if the only thing that’s changed is adding the constructor toTestStandardTetrisThere are probably other and better ways of doing this, so wait to see if any one else comes up with a better answer. 🙂