c# - 如何对私有(private)属性进行单元测试?

标签 c# .net unit-testing testing tdd

我是 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/

相关文章:

c# - 如何使用保存对话框下载文件

c# - 从 azure 函数调用 Web api 的最佳方法

c# - 在 .NET 中解析 URL

c# - WebView cookie Windows 8

c# - 使用插件分析器调试 CRM 2011 插件显示异常消息 "Download the details and load with Plug-in Profiler"

unit-testing - 如何在 Squeak 中自动化单元测试

c# - 重构 ASP.NET——两个控件都继承自 Web.UI.UserControl 并具有相同的属性

c# - 如何扩展一个密封类——需要简单的程序解释和实时使用

linux - 如何使用unix在数据库中登录和执行命令?

unit-testing - 一个单元在哪个级别测试无锁代码?