2

私の Web ストア アプリには、アイテムの合計値を追加、削除、および計算できる「カート」クラスがあります。データ モデルは次のとおりです。1 つのアイテムには 1 つの製品と 1 つの配送が含まれます。Product には Price フィールドがあり、Shipping には Cost フィールドがあります。Cart クラスのコードは次のとおりです。

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);
    }
}

この問題は、おそらくアイテムを製品にバインドし、配送することに関連しています。これどうやってするの?

前もって感謝します!

4

2 に答える 2

2

ここでの根本的な問題は、モデルを永続化する方法の詳細がモデルクラスに漏れており、その結果、モデルを使用するクラス(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

ここでのコストは、ItemsからItemDescriptionsを構築する別のクラスを作成する必要があるということですが、実際にはとにかくそれを行っていたでしょう。それはあちこちで少しずつ行われていたでしょう。追加ItemDescriptionすると明示的になり、より読みやすくなります。確かにもっとテスト可能です。

于 2012-12-29T15:08:29.993 に答える
0

テストメソッドに直接割り当てProductShippingforitem1およびinする必要があります。item2

コード例を参照してください。

[TestMethod]
public void Can_Compute_Total_Values()
{
    // Arrange 
    var item1 = new Item {
        Product = new Product { Price = 10 },
        Shipping = new Shipping { Cost = 2 }
    };

    var item2 = new Item {
        Product = new Product { Price = 20 },
        Shipping = new Shipping { Cost = 5 }
    };

    var target = new Cart();

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

    decimal totalProduct = target.ComputeTotalProductValue();

    // Assert
    Assert.AreEqual(totalProduct, 100);

    Console.ReadLine();
}

コメントで述べたように、リポジトリはテスト中のメソッドでは使用されないため、モックを作成する必要はありません。このメソッドはむしろそれを期待しProductShippingすでに初期化されています。
したがって、テスト用に正しい初期データを手動で準備する必要があります:)。

于 2013-01-01T15:55:54.717 に答える