我在单元测试中遇到一些使用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);
}
}
我收到了这个结果:Test 'Titan.Tests.ShoppingCartTests.ShoppingCart_ShouldIncrementQuantity_WhenAddingDuplicateItem' failed: Expected 3, but found 1.
我感到困惑,或者我只是在愚蠢的时刻!
答案 0 :(得分:4)
这里的问题是,在设置Quantity属性时,您没有告诉Moq要做什么。 默认情况下,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来处理,其中数量属性设置,并在其回调,再设定的属性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;
}
或者,您也可以更改设计,以便不修改公共属性。
答案 1 :(得分:1)
第一项的模拟属性设置为始终返回1.无论你加2,它总是返回1.
编辑:您的+ =被忽略,因为您的购物车存储了模拟对象。首先进入购物车的人被嘲笑为ALWAYs返回1.