C# TDD-由于安排阶段的假设而导致单元测试失败

C# TDD-由于安排阶段的假设而导致单元测试失败,c#,unit-testing,testing,nunit,tdd,C#,Unit Testing,Testing,Nunit,Tdd,我正在做(或试图做)TDD来开发应用程序的业务逻辑 我在一个类中有一个集合,我将其公开为IReadOnlyList,因为我想明确指出,禁止从列表中添加/删除。相反,我公开了AddItem和removietem方法,以便在添加或删除项时可以执行一些其他代码。见下面的例子 public interface IBusinessItem { } public interface IBusinessClass { IReadOnlyList<IBusinessItem> Items {

我正在做(或试图做)TDD来开发应用程序的业务逻辑

我在一个类中有一个集合,我将其公开为
IReadOnlyList
,因为我想明确指出,禁止从列表中添加/删除。相反,我公开了
AddItem
removietem
方法,以便在添加或删除项时可以执行一些其他代码。见下面的例子

public interface IBusinessItem { }
public interface IBusinessClass
{
    IReadOnlyList<IBusinessItem> Items { get; }

    void AddItem(IBusinessItem item);
    void RemoveItem(IBusinessItem item);
}
我认为如果我可以访问
sut.Items.Add(item)
,而不是依赖
sut.AddItem(item)
,那么我的单元测试就不会那么脆弱了,但我不想这样做

我认为这部分解决了我的担忧。我对答案的解释(以及其中一个作者对答案的评论)是,在排列阶段调用其他方法是可以的。但我觉得这可能会导致很多测试失败,除了他们实际测试的原因

我的问题是:在执行TDD时,是否可以访问底层的
列表。添加
(这不是我的公共界面的一部分),以避免依赖我的
removietem
测试中的
添加项
实现

我可以想出几种方法来访问基础
列表。添加

  • 在测试中铸造它
  • 将底层private字段更改为protected,并创建从my BusinessClass继承并公开该字段的mock
  • 将基础私有字段更改为内部,并使用
    InternalsVisibleTo
    属性

如果要公开某些内容,只需创建一个模拟、存根。。。它从基本类继承的版本。继承的版本可能会公开您想要的内容。不需要InternalsVisibleTo。我建议添加一个专门用于接受一组项的测试的构造函数。在构造函数中,直接初始化基础集合,而不调用AddItem。这样,您的安排阶段将不依赖于AddItem。
[Fact]
public void RemoveItemShouldRemoveItemFromItems()
{
    // Arrange
    var item = new MyBusinessItem();
    sut.AddItem(item);
    // Act
    sut.RemoveItem(item); // throws exception if sut.Items is empty
    // Assert
    Assert.Empty(sut.Items);
}