我是 TDD 的新手,我很难理解如何测试类的私有(private)成员(我知道!它是私有(private)的,不应该被测试 - 但请继续阅读)。我们可能有一个设置私有(private)属性的公共(public)函数和其他基于该私有(private)属性返回“某物”的公共(public)函数。
让我给你看一个基本的例子:
public class Cell
{
public int X { get; set; }
public int Y { get; set; }
public string Value { get; set; }
}
public class Table
{
private Cell[,] Cells { get; }
public Table(Cell[,] cells)
{
Cells = cells;
}
public void SetCell(int x, int y, string value)
{
Cells[x, y].Value = value;
}
public void Reset()
{
for (int i = 0; i < Cells.GetLength(0); i++)
{
for (int j = 0; j < Cells.GetLength(1); j++)
{
Cells[i, j].Value = "";
}
}
}
public bool AreNeighborCellsSet(int x, int y)
{
bool areNeighborCellsSet = false;
// checking...
return areNeighborCellsSet;
}
}
在此示例中,Cells
是私有(private)的,因为没有理由将它们公开。我不需要知道这个类之外的特定 Cell
的值是什么。如果相邻单元格为空,我只需要一个信息。
<强>1。如何测试 Reset
方法?
从技术上讲,我应该创建一个包含模拟单元格数组的表格。调用 Reset
,然后断言每个单元格的 Value
是否为空。但我实际上无法检查它们是否为空。
<强>2。在这种情况下,我会多次调用 Assert
(针对每个单元格)——这是一种好的做法吗?我读到“不是!”,但重置会重置所有单元格,因此我必须以某种方式检查每个单元格。
编辑: 选项 2:
public class Table
{
private Cell[,] Cells { get; }
public Table(int height, int width, ICellFactory cellFactory)
{
Cells = new ICell[height, width];
for (int i = 0; i < Cells.GetLength(0); i++)
{
for (int j = 0; j < Cells.GetLength(1); j++)
{
Cells[i, j].Value = cellFactory.Create(i, j);
}
}
}
// Rest is the same...
}
最佳答案
你的类有三个公共(public)方法
void SetCell
void Reset
bool AreNeighborCellsSet
因此,所有功能都应仅通过这些方法并在构造函数输入参数的可能帮助下进行测试。
恐怕你没有在做 TDD,因为你正在尝试测试已经实现的逻辑(内部成员的 for
循环)。使用 TDD,您应该仅使用被测类的公共(public) API 来编写单元测试。
当您测试Reset
方法时,您应该考虑它如何影响其他公共(public)方法的结果。 Table
类只有一个方法可以返回一些我们可以观察到的值 - bool AreNeighborCellsSet
- 所以看起来这是我们可以执行断言的唯一方法。
对于 Reset
方法,您需要设置单元格以便 AreNeighborCellsSet
返回 true
。然后执行 Reset
并断言现在 AreNeighborCellsSet
返回 false。
[Test]
public void AfterResetGivenCellShouldNotHaveNeighbors()
{
// Arrange
var cell = new Cell { X = 1, Y = 1, Value = "central" };
var neighborCell = new new Cell { X = 1, Y = 2, Value = "neighbor" };
var table = new Table(new[] { cell, neighborCell });
// table.AreNeighborCellsSet(cell.X, cell.Y) - should return true at this moment
// Act
table.Reset();
// Assert
table.AreNeighborCellsSet(cell.X, cell.Y).Should().BeFalse();
}
这是 TDD(测试驱动开发)的一个很好的例子,其中测试问题是设计有问题的好兆头。
实际上,我认为,在您的情况下,您根本不需要 Reset
方法 - 只需在每次需要重置时创建一个新的 Table
实例。
关于c# - 如何对私有(private)属性进行单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43417626/