C# 在这种简单的情况下,如何保持单元测试彼此独立?

C# 在这种简单的情况下,如何保持单元测试彼此独立?,c#,unit-testing,tdd,C#,Unit Testing,Tdd,我正在用C#编写一个小游戏,使用测试驱动的开发方法。我面临一个问题: 我有一个类棋盘: public class CheckersBoard { private const string InitialBoardPattern = "B-B-B-B-" + "-B-B-B-B" + "B-B-B-B-"

我正在用C#编写一个小游戏,使用测试驱动的开发方法。我面临一个问题:

我有一个类
棋盘

public class CheckersBoard
{
    private const string InitialBoardPattern = "B-B-B-B-" +
                                               "-B-B-B-B" +
                                               "B-B-B-B-" +
                                               "--------" +
                                               "--------" +
                                               "-W-W-W-W" +
                                               "W-W-W-W-" +
                                               "-W-W-W-W";

    public SquareStatus[,] Squares { get; private set; }

    public CheckersBoard(IBoardGenerator boardGenerator)
    {
        Squares = boardGenerator.GenerateFromPattern(InitialBoardPattern, 8, 8);
    }

    //....
}
和一个类
BoardGenerator

public class BoardGenerator : IBoardGenerator
{

    public SquareStatus[,] GenerateFromPattern(string pattern, int width, int height)
    {
        //....
    }

}
BoardGenerator
允许我以非常可读的方式初始化
checkerboard
。因此,我真的希望在单元测试中使用
BoardGenerator
,以避免难看的数组初始化

但这违反了我必须让所有单元测试彼此独立的规则。如果
GenerateFromPattern
的测试失败,将产生“级联”效应,所有使用
GenerateFromPattern
的测试也将失败

这是我第一次使用单元测试,所以我有点困惑。我怎样才能避免这个问题?我的设计有什么问题吗

您可以使用您的
BoardGenerator
类,也可以伪造实现,例如

internal class MockBoardGenerator : IBoardGenerator
{
    public SquareStatus[,] GenerateFromPattern(string pattern, int width, int height)
    {
        // return fixed test data
    }
}

显然,这是一个没有明显答案的常见问题,我碰巧遇到了两个类似的问题:

  • -建议反对,因为OP讨论了两个不同的组件(与您的案例类似)
  • -为建议,因为使用范围仅限于单个类(这样新的bug就不可能使一些完全无关的组件崩溃,而是所有的bug都将保持在原来的“崩溃范围”内)
在某种程度上,重用业务逻辑(其他经过测试的组件)类似于在单元测试中使用第三方库——我们假设它们可以工作,并且不需要为它们生成额外的断言。在单元测试中使用
列表
会有任何犹豫吗?最有可能的答案是否定的。然而,请注意,
List
每天都会被许多其他开发人员测试,并且背后有一家大型软件公司。你能对BoardGenerator说同样的话吗


另一个要考虑的问题是,<代码>棋盘> <代码>测试代码对于那些从来没有在<代码> BoardGenerator < /代码>上工作过的人来说是显而易见的吗?你声称它是可读的,但考虑到创作,这是很常见的。也许使用数组初始化并不像你想象的那么糟糕(不可读)。

谢谢你的回答,但我已经在嘲笑它了。我的问题是我想在测试中以可读的方式初始化我的游戏板,以使它们易于理解。所以我真的想使用字符串初始化而不是数组初始化。@user1642427很抱歉,您没有提到您在最初的问题中已经在模拟您的电路板。“我真的想使用字符串初始化而不是数组初始化”-您的
BoardGenerator
能否支持这两种方法,只支持字符串一种进行测试?是的,我表达得不太好。对不起
GenerateFromPattern
是一种排序辅助方法,用于优雅地初始化我的电路板。所以我在生产项目和测试项目中都需要它。我需要它的真正实现,以使我的测试更具可读性。也许可以在我的测试项目中克隆它。我将有一个BoardHelper静态类,它将在我的测试项目中完成相同的工作。但对我来说这听起来有点难看…听起来你想用这个。这样,您就可以拥有一个单独的
TestBoardGenerator
类,该类重写
GenerateFromPattern
的行为。这是一个误解。我不想覆盖
TestBoardGenerator
中的任何内容。我想在单元测试中使用
GenerateFromPattern
方法的默认实现。所以问题是:“我能在另一个单元测试中使用这个方法并假设它有效吗?”。吉米·基恩(jimmy_keen)的答案对这个问题提供了大量信息。谢谢你的帮助@James!非常感谢您的回答!正如我所说,这是我第一个使用单元测试的项目。我只是想让自己熟悉这个概念。所以,我想确保我知道如何在未来面对类似的问题。我现在似乎明白了,谢谢!