asp.net - 如何在 Asp.Net MVC 3 中对使用带有子实体的数据模型的类进行单元测试

标签 asp.net asp.net-mvc asp.net-mvc-3 unit-testing moq

在我的网上商店应用程序中,我有一个“购物车”类,可以添加、删除和计算商品的总值(value)。数据模型如下:1 个项目包含 1 个产品和 1 个运输。产品有价格字段,运输有成本字段。这是购物车类代码:

public class CartLine
{
    public Item Item { get; set; }
    public int Quantity { get; set; }
}

public class Cart
{
    private List<CartLine> lineCollection = new List<CartLine>();

    // methods: 
    // Add(Item item, int quantity) 
    // Remove(Item item)

    public decimal ComputeTotalProductValue()
    {
        return lineCollection.Sum(l => l.Item.Product.Price*l.Quantity);
    }

    // methods with the same principle: 
    // ComputeTotalShippingValue()
    // ComputeOveralValue()
}

这是我的单元测试(当然不起作用):

[TestMethod]
    public void Can_Compute_Total_Values()
    {
        // Arrange 
        var itemMock = new Mock<IItemsRepository>();
        itemMock.Setup(i => i.GetItems()).Returns(new[]
            {
                new Item { ItemId = 1, ProductId = 1, ShippingId = 1 },
                new Item { ItemId = 2, ProductId = 2, ShippingId = 2 }
            });

        var productMock = new Mock<IProductRepository>();
        productMock.Setup(p => p.GetProducts()).Returns(new[]
            {
                new Product { ProductId = 1, Price = 10 },
                new Product { ProductId = 2, Price = 20 }
            });

        var shippingMock = new Mock<IShippingRepository>();
        shippingMock.Setup(s => s.GetShippings()).Returns(new[]
            {
                new Shipping { ShippingId = 1, Cost = 2 },
                new Shipping { ShippingId = 2, Cost = 5 }
            });

        var item1 = itemMock.Object.GetItems().ToArray()[0];
        var item2 = itemMock.Object.GetItems().ToArray()[1];    

        var target = new Cart();

        //Act
        target.Add(item1, 2);
        target.Add(item2, 4);

        decimal totalProduct = target.ComputeTotalProductValue();
        decimal totalShipping = target.ComputeTotalShippingValue();
        decimal overalSum = target.ComputeOveralValue();

        // Assert
        Assert.AreEqual(totalProduct, 100);
        Assert.AreEqual(totalShipping, 24);
        Assert.AreEqual(overalSum, 124);
    }
}

该问题可能与将商品绑定(bind)到产品和运输有关。我怎样才能做到这一点?

提前致谢!

最佳答案

这里的根本问题是,有关如何持久化模型的详细信息已泄漏到模型类中,因此使用模型的类(例如 Cart 使用 Item)有一定义务了解您的持久层,它们应该不需要做。这是太多的耦合,这使得你的测试变得困难。

考虑重新定义Item并添加 ItemDescription像这样:

public class Item
{
   public Product Product {get;set;}
   public Shipping Shipping {get;set;}
}

public class ItemDescription
{
   public int ProductId {get;set;}
   public int ShippingId {get;set;}
}

这允许您测试购物车以及使用您的 Item 的其他类上课相当轻松。如果您需要的话,我可以添加一个示例,但我猜这对您来说非常明显。如果你无法改变Item由于某种原因,请颠倒此方法并创建一个 FullyConsitituedItem为您上课Cart使用。

这里的代价是你必须创建另一个构造 Item 的类。来自 ItemDescription s,但无论如何你实际上都会这样做,它只是在各处零碎地完成。添加ItemDescription使其变得明确,这更好,更具可读性。当然更容易测试。

关于asp.net - 如何在 Asp.Net MVC 3 中对使用带有子实体的数据模型的类进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14081332/

相关文章:

c# - 将图像上传到S3

asp.net-mvc-3 - jquery.validate.unobtrusive 不适用于动态注入(inject)元素

c# - 需要在 asp.net webforms 中为热敏打印机设计 html 页面

jQuery Mobile 和 ASP.NET 更新面板问题

c# - MembershipCreateStatus.InvalidPassword 如果我传递简单的词

c# - 如何在自定义 WebViewPage 中设置属性?

c# - 如何从C#中的特定资源文件中获取字符串资源

javascript - ASP.NET MVC/JavaScript - 从 C# amp 解码编码的 HTML 字符串

c# - 如何从 ASP.NET MVC3 中的局部 View 发布数据?

javascript - 在后面的asp.net代码中调用类点击功能