c#-最小起订量-如何验证是否通过s设置了属性值

考虑此类:

public class Content
{      
   public virtual bool IsCheckedOut {get; private set;}
   public virtual void CheckOut()
   {
      IsCheckedOut = true;
   }

   public virtual void CheckIn()
   {
      //Do Nothing for now as demonstrating false positive test.
   }
}

Checkin方法有意为空。 现在,我有一些测试方法来验证调用每个方法的状态。

[TestMethod]
public void CheckOutSetsCheckedOutStatusToTrue()
{
    Content c = new Content();    
    c.CheckOut();
    Assert.AreEqual(true, c.IsCheckedOut); //Test works as expected
}

[TestMethod]
public void CheckInSetsCheckedOutStatusToFalse()
{
    Content c = new Content();
    c.CheckIn();
    Assert.AreEqual(false, c.IsCheckedOut); //Test does not work as expected
}

由于错误原因,第二次测试通过。 那么,如何使用模拟(moq)来验证CheckIn设置了IsCheckedOut属性?

谢谢。

编辑

需要说明的是:我有一个称为CheckIn()的方法,其作用是将IsCheckedOut状态设置为false。

您将在上面的测试代码中看到,即使我未将属性值设置为false,测试也将返回false。 这是预料之中的,这里没有错。

我认为我的问题特别是如何验证Check In()方法是否已将IsChecked Out属性设置为false? 这就是我所说的行为验证。

我相信某些评论建议做一些等同于状态验证的事情? 如果是这样,我不相信在我们可以简单使用的情况下完全嘲笑这一部分没有任何价值:

Content c = new Content();    
c.CheckIn();    
Assert.AreEqual(false, c.IsCheckedOut); //State verification

当然我可能是错的,所以请帮助我阐明这些概念:)

Konamiman asked 2020-08-12T01:17:35Z
5个解决方案
41 votes

以下应该工作。 将模拟对象配置为:

var mock=new Mock<IContent>();
mock.SetupSet(content => content.IsCheckedOut=It.IsAny<bool>()).Verifiable();

并在测试代码之后:

mock.VerifySet(content => content.IsCheckedOut=It.IsAny<bool>());

无论如何我都没有测试过,所以请告诉我它是否适合您。

编辑。 确实,这将不起作用,因为IsCheckedOut的设置程序是错误的。

无论如何,现在我看到您从未在类构建时设置IsCheckedOut的值。 将以下内容添加到300743938121819851985类中是一个好主意:

public Content()
{
    IsCheckedOut=false;
}
Konamiman answered 2020-08-12T01:17:58Z
19 votes
Mock mockContect = new Mock<Cotent>(); 
mockContent.VerifySet(x => x.IsCheckedOut, Times.Once());

那会成功吗? 不确定私有的二传手如何进入比赛,因为还没有经过测试。 但适用于我的公众二传手。

从以下网站获得此信息:[http://www.codethinked.com/post/2009/03/10/Beginning-Mocking-With-Moq-3-Part-2.aspx]

Dominic answered 2020-08-12T01:18:23Z
4 votes

为什么不简单地设置要签出的内容呢? 请记住,您只是在测试CheckIn函数的行为。

[TestMethod]
public void CheckInSetsCheckedOutStatusToFalse()
{
    // arrange - create a checked out item
    Content c = new Content();
    c.CheckOut();

    // act - check it in
    c.CheckIn();

    // assert - IsCheckedOut should be set back to false
    Assert.AreEqual(false, c.IsCheckedOut);
}
Mark Heath answered 2020-08-12T01:18:44Z
2 votes

我可以建议您以错误的方式进行思考吗?通常情况下,您应该先进行设置,执行操作,然后检查行为(结果)。 在这种情况下,设置者未将其设置为false真的很重要-重要的是,在执行给定方案之后,它为false。 如果您单独进行测试,这似乎有些奇怪,但是对于任何测试,您的测试都将成组存在。

如果要测试两个类之间的交互,情况将有所不同-那么可以对属性设置器设置期望值就可以了-因为设置操作是您正在测试的交互。

我不熟悉Moq,因为我使用Rhino.Mocks-但我猜可能会有一些类似模仿的东西。

FinnNk answered 2020-08-12T01:19:14Z
0 votes

我同意你的看法:在这种情况下,模拟没有任何价值,因为模拟旨在测试您的类(被测试)与世界其他地方之间的交互,而不是测试类的内部机制。

我认为这个测试

Content c = new Content();    
c.CheckIn();    
Assert.AreEqual(false, c.IsCheckedOut); //State verification

你写的很有道理,不是假阳性! 您必须确保签入后的状态为这种状态,无论原因为何; 如果将来您将在构造函数(或其他方法)中设置状态,则此测试将为您节省时间,并且您将被迫实施CheckIn方法!

在某些情况下,与您类似,我想设置初始状态以确保我不会忘记实现CheckIn方法。 在这种情况下,我使用2种方法(第一种非常难看):

  1. 我在c.CheckIn()之前调用c.CheckOut(); 这非常丑陋,因为您测试了2种方法而不是一种方法...但是我承认我写了类似的东西几次:-)
  2. 我保护了私有的设置器,并编写了一个测试类从被测类继承; 以这种方式我可以设置属性设置为true,然后再调用c.CheckIn()以确保方法正在完成他的工作。

这是代码:

    public class Content2
{
    public virtual bool IsCheckedOut { get; protected set; }
    public virtual void CheckOut()
    {
        IsCheckedOut = true;
    }

    public virtual void CheckIn()
    {
        //Do Nothing for now as demonstrating false positive test.
    } 
}

    [TestClass]
public class Content2Test : Content2
{
    [TestMethod]
    public void CheckOutSetsCheckedOutStatusToTrue()
    {
        this.CheckOut();
        Assert.AreEqual(true, this.IsCheckedOut); //Test works as expected
    }

    [TestMethod]
    public void CheckInSetsCheckedOutStatusToFalse()
    {
        this.IsCheckedOut = true;
        this.CheckIn();
        Assert.AreEqual(false, this.IsCheckedOut); //Test does not work as expected
    }
}

希望对您有所帮助。

Daniele Armanasco answered 2020-08-12T01:20:06Z
translate from https://stackoverflow.com:/questions/1641919/moq-how-to-verify-that-a-property-value-is-set-via-the-setter