c# - 如何验证模拟对象是否已从模拟列表中删除?

标签 c# list unit-testing mocking moq

我正在尝试为此方法编写单元测试:

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/

相关文章:

c# - 防止相机离开地形

c# - DataGridView 使用基于枚举的 Combobox 列链接到 DataTable

html - 如何测试网页上粗体文本的百分比?

c++ - 在 C++ 源文件中包含 C++11 头文件

c# - 具有 Linq to Sql 扩展的 DateTime 的子字符串

c# - 如果结构包含 DateTime 字段,为什么 LayoutKind.Sequential 的工作方式不同?

python - 如何返回列表项的索引

python - 在 Python 2.3 中按项目频率对列表列表进行排序

python - 删除带有外国字母号码的列表

c# - 如何让 nunit-console 在\bin\Debug\而不是\bin\x86\Debug 中查找程序集?