我正在(或尝试做)TDD为应用程序开发我的业务逻辑。
我在一个类中有一个集合,我公开为db.changerecord.update({"extSystem":{"$exists":true}}, {$rename:{"extSystem.extCRid":"extSystem.extId"}}, false, true);
,因为我想明确表示禁止从列表中添加/删除。相反,我公开了IReadOnlyList
和AddItem
方法,以便在添加或删除项目时可以执行其他一些代码。见下面的例子。
RemoveItem
当我尝试遵循单位测试should fail for one reason only的原则时,我的问题就出现了。单元测试我的public interface IBusinessItem { }
public interface IBusinessClass
{
IReadOnlyList<IBusinessItem> Items { get; }
void AddItem(IBusinessItem item);
void RemoveItem(IBusinessItem item);
}
要求我在测试安排阶段使用RemoveItem
。因此,我的测试可能会失败,因为AddItem
没有按预期删除项目,或者因为RemoveItem
没有按预期工作,因此AddItem
会抛出:
RemoveItem
如果我可以访问[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);
}
而不是依赖sut.Items.Add(item)
,我认为我的单元测试不会那么脆弱,但我不想{{3} }。
我认为change my public interface just for testing purposes部分地解决了我的担忧。我对答案的解释(以及answer对答案的评论之一)是在排列阶段调用其他方法。但我觉得这可能会导致很多测试由于其他原因而失败,而不是他们实际测试的原因。
我的问题是:在进行TDD时,访问底层sut.AddItem(item)
(不是我的公共接口的一部分)是可以接受的,以避免依赖{{1我的List.Add
测试中的实现?。
我可以通过几种方式来访问基础AddItem
:
RemoveItem
属性