我正在尝试为此方法编写单元测试:
public void AddItem( Cart cart, Item item )
{
var duplicates = cart.Items.OfType<Item>()
.Where( i => i.Key == item.Key )
.ToList();
foreach ( var duplicate in duplicates )
{
cart.Items.Remove( duplicate );
}
cart.Items.Add( item );
}
我想验证在添加新项目之前是否已从列表中删除重复项目(具有相同键的项目)。此测试失败:
[TestMethod]
public void AddItemRemovesDuplicateItemsFirst()
{
const int itemKey = 123;
var cart = new Mock<Cart>();
var duplicate = new Mock<Item>();
duplicate.SetupGet( m => m.Key ).Returns( itemKey );
cart.SetupGet( m => m.Items ).Returns( new List<Item>
{
duplicate.Object
} );
var addItem = new Mock<Item>();
addItem.SetupGet( m => m.Key ).Returns( itemKey );
var task = GetTask();
task.AddItem( cart.Object, addItem.Object );
Assert.AreEqual( 1, cart.Object.Items.Count );
}
它失败了,因为 Count
是 2。另一方面,这个测试通过了:
[TestMethod]
public void AddItemRemovesDuplicateItemsFirst()
{
const int itemKey = 123;
var cart = new Mock<Cart>();
cart.SetupGet( m => m.Items ).Returns( new List<Item>
{
new Item
{
Key = itemKey
}
} );
var addItem = new Mock<Item>();
addItem.SetupGet( m => m.Key ).Returns( itemKey );
var task = GetTask();
task.AddItem( cart.Object, addItem.Object );
Assert.AreEqual( 1, cart.Object.Items.Count );
}
唯一的区别是第二个不使用 Mock
对象作为列表项。
我试图避免像第二种方法那样实际创建对象。如何才能第一个通过?
最佳答案
由于您正在测试的是与 Items
的交互,因此您将需要一个对象来测试,无论它是具体实例(如第二种方法中所示)还是模拟。
如果您使用模拟,则需要将其设置为在调用 OfType
时返回现有项目。然后,您可以显式验证是否调用了 Remove
,而不是检查 Count
,如下所示(未测试):
Items.Verify(
x => x.Remove(
It.Is<Item>(
item => item.Key == itemKey)));
话虽如此,我不禁想到这个功能应该封装在 Cart
中,而不暴露要在该类外部操作的 Item
列表。这也将使编写测试变得更容易。
关于c# - 如何验证模拟对象是否已从模拟列表中删除?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22185166/