C# UnitTest-当测试方法来自模拟时发出

C# UnitTest-当测试方法来自模拟时发出,c#,unit-testing,tdd,C#,Unit Testing,Tdd,我有一个类使用一个接口,它有一个void方法,看起来像这个witch现在是完全有效的方法: public void SellGivenQuantityOfProduct(Product product, int quantity) { product.StockQuantity = product.StockQuantity - quantity; } 但是以TDD的方式工作,我开始像下面这样做,但是在我的测试方法中从未进行过计算 [TestMethod] public

我有一个类使用一个接口,它有一个void方法,看起来像这个witch现在是完全有效的方法:

public void SellGivenQuantityOfProduct(Product product, int quantity)
{
    product.StockQuantity = product.StockQuantity - quantity;
}
但是以TDD的方式工作,我开始像下面这样做,但是在我的测试方法中从未进行过计算

    [TestMethod]
    public void Can_Sell_Given_Quantity_Of_Single_Products_Stock_Quantity()
    {
        var mock = new Mock<ISellBuyPipeLine>();
        mock.Setup(o => o.Products).Returns(new Product[]
        {
            new Product() {ArticleNr = 87, StockQuantity = 10}
        });
        var product = mock.Object.Products.First();
        var choosenProductToSell = new SellBuyProduct() {Product = product, Quantity = 5};
        mock.Object.SellGivenQuantityOfProduct(product, choosenProductToSell.Quantity);

        /*var test = new SellBuyPipeLine();
        test.SellGivenQuantityOfProduct(product, choosenProductToSell.Quantity);*/

        int expectedSellValue = product.StockQuantity;

        Assert.AreEqual(5, expectedSellValue);
    }
[TestMethod]
公共无效可以出售给定数量的单一产品库存数量()
{
var mock=new mock();
mock.Setup(o=>o.Products).Returns(新产品[]
{
新产品(){ArticleNr=87,StockQuantity=10}
});
var product=mock.Object.Products.First();
var choosenProductToSell=new SellBuyProduct(){Product=Product,Quantity=5};
mock.Object.SellGivenQueantyOfProduct(产品,选择ProductToSell.Quantity);
/*var测试=新的SellBuyPipeLine();
test.sellgivenqueantyofproduct(产品,选择ProductToSell.Quantity)*/
int expectedSellValue=product.StockQuantity;
Assert.AreEqual(5,expectedSellValue);
}
如果我使用的是outcommented行并直接命中持有我的方法的类,那么它就可以工作了!但是我想用模拟的

我做错了什么


我是否使用了错误的方法?

如果要测试实现,请测试实现。模拟对象的方法不包含实现

您可能希望模拟
产品
,使测试方法看起来像这样:

public void Can_Sell_Given_Quantity_Of_Single_Products_Stock_Quantity()
{
    // Arrange
    int stockQuantity = 10;
    int quantityToSell = 4;
    int newQuantity = 6;

    var productMock = new Mock<Product>(MockBehavior.Strict);
    productMock.SetupGet(p => p.StockQuantity).Returns(stockQuantity);
    productMock.SetupSet(p => p.StockQuantity = newQuantity);

    var classUnderTest = new SellBuyPipeLine();

    // Act
    test.SellGivenQuantityOfProduct(product, quantityToSell);

    // Assert
    productMock.VerifySet(p => p.StockQuantity, Times.Once());
}
public void可以销售给定数量的单个产品库存数量()
{
//安排
国际库存量=10;
int quantityToSell=4;
int newQuantity=6;
var productMock=newmock(MockBehavior.Strict);
productMock.SetupGet(p=>p.StockQuantity).Returns(StockQuantity);
productMock.SetupSet(p=>p.StockQuantity=newQuantity);
var classUnderTest=新的SellBuyPipeLine();
//表演
测试。销售抗纤产品(产品,数量销售);
//断言
productMock.VerifySet(p=>p.StockQuantity,Times.Once());
}

您可以不使用,因为产品不包含任何逻辑,在这种情况下,只需实例化
新产品
,并断言其
库存数量
等于
新数量

除非您的
产品
类包含实际的业务逻辑,否则不要模仿它。我建议尽可能在编写测试时假装愚蠢

[TestMethod]
public void Can_Sell_Given_Quantity_Of_Single_Products_Stock_Quantity()
{
    var product = new Product { ArticleNr = 87, StockQuantity = 10 };

    var pipeline = new SellBuyPipeLine();
    pipeline.SellGivenQuantityOfProduct(product, 5);

    Assert.AreEqual(5, product.StockQuantity);
}
愚蠢的(非常简单的)测试导致了愚蠢的简单生产代码,这正是您想要的


尽可能避免对调用进行严格的模拟和断言,因为这会使测试变得脆弱。

Ok!我应该测试一下我推荐的台词吗?或者正确的方法是什么?SellGivenQueantyOfProduct方法在我的界面中。为什么通过接口模拟测试它是错误的?或者在我的界面中使用这个方法是错误的吗?把它放在我的产品类中会更好吗?基本上是因为你嘲笑你不想测试的东西。您正在测试SellGivenQueantyOfProduct实现。否。这只是意味着,如果你想测试一个使用
isellbuypippeline
的类,你可以模拟
isellbuyppeline
。在这种情况下,我的答案完全足够了,也更简单了。所以,是的,我确实认为这是一条路要走。@CodeCaster谢谢你的回答!这是我第一次使用的方法。是的,我的方法没有任何商业逻辑。现在来回答这个问题:Witch方法是最好使用的:user bsrenzel vs user CodeCaster?您正在测试的
sellgivenkuantityofproduct
方法应该包含业务逻辑。这就是你测试的开始。如果产品仅仅是一个数据传输对象,则不需要对其进行模拟。您实际模拟的是依赖项,即另一个类持有对通过构造函数注入的
isellbuypippeline
实例的引用。在这种情况下,您将使用模拟对象(而不是真实对象)实例化该类。这是指商业逻辑吗?是的。但这不是重点。关键是在单元测试中只测试当前类的功能(
sellbuypippeline
)。如果
产品
具有主要功能,则必须确保可以模拟
产品
(例如,通过提取接口并将
SellBuyPipeLine
更改为依赖该接口),因此,您可以针对
SellBuyPipeLine
编写测试,而无需同时测试
Product
。魔鬼代言人:实现
Product.StockQuantity=5
将通过此测试,但不会实现“按给定数量减少库存数量”的要求。