unit-testing - 使用最小起订量的奇怪行为

标签 unit-testing moq

我在单元测试中使用最小起订量时遇到一些奇怪的行为:

给出以下测试:

[Fact]
public void ShoppingCart_ShouldIncrementQuantity_WhenAddingDuplicateItem()
{
    var cart = new ShoppingCart();

    var item1 = GetMockItem("Test");
    var item2 = GetMockItem("Test", quantity: 2);

    cart.AddItem(item1.Object);
    cart.AddItem(item2.Object);

    cart.Items.Single(x => x.Sku == "Test").Quantity
        .Should().Be(3);
}

private Mock<IShoppingCartItem> GetMockItem(string sku, decimal price = 10, int quantity = 1)
{
    var mock = new Mock<IShoppingCartItem>();
    mock.Setup(x => x.Sku).Returns(sku);
    mock.Setup(x => x.Price).Returns(price);
    mock.Setup(x => x.Quantity).Returns(quantity);

    return mock;
}

这是正在测试的代码:

public void AddItem(IShoppingCartItem item)
{
    Enforce.ArgumentNotNull(item, "item");

    var existingItem = this.Items.SingleOrDefault(x => x.Sku == item.Sku);

    if (existingItem != null)
    {
        existingItem.Quantity += item.Quantity;
    }
    else
    {
        this.Items.Add(item);
    }
}

我得到以下结果:测试“Titan.Tests.ShoppingCartTests.ShoppingCart_ShouldIncrementQuantity_WhenAddingDuplicateItem”失败:预期为 3,但发现为 1。

我很困惑,或者我只是有一个愚蠢的时刻!

最佳答案

这里的问题是,您没有告诉 Moq 在设置 Quantity 属性后要做什么。 默认情况下,Moq 不仅仅假设您的所有属性都应该是简单的 getter/setter。由您决定如何处理它们。

您有几个选择。

使用SetupAllProperties()告诉Moq将属性视为简单的getter/setter。

  private Mock<IShoppingCartItem> GetMockItem(string sku, decimal price = 10, int quantity = 1)
  {
        var mock = new Mock<IShoppingCartItem>();
        mock.SetupAllProperties();

        // Set the properties like normal properties. Moq will do the right thing.
        mock.Object.Sku = sku;
        mock.Object.Price = price;
        mock.Object.Quantity = quantity;
        return mock;
  }

使用SetupSet处理设置Quantity属性的情况,并在其回调中重新设置属性getter,以便它返回新值。

  private Mock<IShoppingCartItem> GetMockItem(string sku, decimal price = 10, int quantity = 1)
  {
        var mock = new Mock<IShoppingCartItem>();
        mock.Setup(x => x.Sku).Returns(sku);
        mock.Setup(x => x.Price).Returns(price);
        mock.Setup(x => x.Quantity).Returns(quantity);

        // You can call Setups from within Setups
        mock.SetupSet(x => x.Quantity).Callback(q => mock.Setup(x => x.Quantity).Returns(q));
        return mock;
  }

或者,您也可以更改设计,这样就不会修改公共(public)属性。

关于unit-testing - 使用最小起订量的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18240657/

相关文章:

c# - 如何在方法设置中为数组起订 It.IsAny?

c# - 如何使用 Moq.MockRepository.Of() 方法

c# - 如何在测试方法 Moq 中设置查询字符串的值

angular - 测试包含自定义表单控件的 Angular 组件?

python - 在 Python 中测试私有(private)方法 : Unit Test or Functional Test?

c# - Moq 具有 5 个以上参数和访问调用参数的函数

c# - 模拟调用异常为 0 次,但我可以正确看到执行的调用

ruby - RSpec : How to test file parser

javascript - 测试 AngularUI Bootstrap 模式实例 Controller

java - 如何避免重复捕获模拟方法的异常,这些异常可能会根据接口(interface)抛出异常