C# Moq - 如何验证是否通过 setter 设置了属性值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1641919/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Moq - How to verify that a property value is set via the setter
提问by
Consider this class:
考虑这个类:
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.
}
}
The Checkin method is intentionally empty. Now i have a few test methods to verify the status of calling each method.
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
}
The 2nd test passes for the wrong reasons. So how can i use mocking (moq) to verify that CheckIn is setting the IsCheckedOut property?
第二个测试由于错误的原因而通过。那么我如何使用模拟 (moq) 来验证 CheckIn 是否设置了 IsCheckedOut 属性?
Thanks.
谢谢。
EDIT
编辑
To clarify: I have a method called CheckIn() whose job it is to set the IsCheckedOut status to false.
澄清一下:我有一个名为 CheckIn() 的方法,它的工作是将 IsCheckedOut 状态设置为 false。
You will see in my test code above that the Test will return false even if i do not set the property value to false; This is expected, nothing wrong here.
您将在上面的测试代码中看到,即使我没有将属性值设置为 false,测试也会返回 false;这是意料之中的,这里没有错。
I think my question specifically is How can i verify that the CheckIn() method has set the IsCheckedOut property to false? This is what I would call behavioral verification.
我认为我的问题特别是如何验证 CheckIn() 方法是否已将 IsCheckedOut 属性设置为 false?这就是我所说的行为验证。
I believe some of the comments suggested doing something which amounts to state verification? If so I don't believe there is any value in mocking this part at all when we can simply use:
我相信有些评论建议做一些相当于国家验证的事情?如果是这样,我认为当我们可以简单地使用以下内容时,嘲笑这部分根本没有任何价值:
Content c = new Content();
c.CheckIn();
Assert.AreEqual(false, c.IsCheckedOut); //State verification
Of course I may be wrong, so please help me clarify these concepts :)
当然我可能是错的,所以请帮我澄清这些概念:)
回答by Konamiman
The following should work. Configure your mock object as:
以下应该工作。将您的模拟对象配置为:
var mock=new Mock<IContent>();
mock.SetupSet(content => content.IsCheckedOut=It.IsAny<bool>()).Verifiable();
And after the test code:
在测试代码之后:
mock.VerifySet(content => content.IsCheckedOut=It.IsAny<bool>());
I haven't tested it anyway, so please tell me if it works for you.
反正我还没有测试过,所以请告诉我它是否适合你。
EDIT. Indeed, this will not work since the setter for IsCheckedOut
is false.
编辑。事实上,这不会起作用,因为 for 的 setterIsCheckedOut
是假的。
Anyway, now I see that you never set the value of IsCheckedOut
at class construction time. It would be a good idea to add the following to the Content
class:
无论如何,现在我看到您从未IsCheckedOut
在类构建时间设置值。将以下内容添加到Content
类中将是一个好主意:
public Content()
{
IsCheckedOut=false;
}
回答by FinnNk
Can I suggest that you might be thinking about this in the wrong way - generally you should be setting something up, performing an action and then checking the behaviour (result). In this case does it really matter that it wasn't set to false by the setter - what should matter is that it is false in after a given scenario has been exercised. If you take tests in isolation this might seem a bit odd, but for anything your tests will exist in sets.
我是否可以建议您以错误的方式考虑这个问题 - 通常您应该设置一些东西,执行一个操作然后检查行为(结果)。在这种情况下,setter 没有将它设置为 false 真的很重要 - 重要的是在执行给定场景之后它是 false 。如果您单独进行测试,这可能看起来有点奇怪,但是对于任何事情,您的测试都将存在于集合中。
The situation would be different if you were testing the interaction between two classes - then it would be fine to set up an expectation on the property setter - as the setting action is the interaction you're testing.
如果您正在测试两个类之间的交互,情况会有所不同 - 那么在属性设置器上设置期望就可以了 - 因为设置操作是您正在测试的交互。
I'm not familiar with Moq as I use Rhino.Mocks - but I'm guessing there'll be something along the lines of mock.VerifySet(content => content.IsCheckedOut=It.IsEqual(true));
我不熟悉 Moq,因为我使用 Rhino.Mocks - 但我猜会有类似 mock.VerifySet(content => content.IsCheckedOut=It.IsEqual(true)); 的东西。
回答by Mark Heath
why don't you simply set up the content to be checked out to start with? Remember, you are only testing the behaviour of the CheckIn function.
为什么不简单地设置要检出的内容开始呢?请记住,您只是在测试 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);
}
回答by Dominic
Mock mockContect = new Mock<Cotent>();
mockContent.VerifySet(x => x.IsCheckedOut, Times.Once());
Will that do the trick? Not sure how the private setter comes in to play as havent tested that. but works for my public setter.
这会奏效吗?不确定私人二传手如何发挥作用,因为尚未对此进行测试。但适用于我的公共二传手。
Got this from: http://www.codethinked.com/post/2009/03/10/Beginning-Mocking-With-Moq-3-Part-2.aspx
来自:http: //www.codethinked.com/post/2009/03/10/Beginning-Mocking-With-Moq-3-Part-2.aspx
回答by Daniele Armanasco
I agree with you: mocking has no value in this scenario because it is intended to test the interactions between your class (under test) and the rest of the world, not to test the inner mechanism of your class.
我同意你的看法:mocking 在这种情况下没有价值,因为它旨在测试你的类(被测类)和世界其他地方之间的交互,而不是测试你的类的内部机制。
I think that this test
我认为这个测试
Content c = new Content();
c.CheckIn();
Assert.AreEqual(false, c.IsCheckedOut); //State verification
that you write has sense and it is not a false positive! You must ensure that the state is in that way after the CheckIn regardless on why it is so; if in the future you will set the state in the constructor (or in other methods) this test will save you and you will be forced to implement the CheckIn method!
你写的有道理,不是误报!你必须确保在 CheckIn 之后状态是那样的,不管它为什么是这样;如果将来您将在构造函数(或其他方法)中设置状态,则此测试将拯救您,并且您将被迫实现 CheckIn 方法!
In some cases similar to your I want to set the initial state to be sure that I does not forget to implement the CheckIn method; in this case I use 2 methods (the first is very ugly):
在某些类似于您的情况下,我想设置初始状态以确保我不会忘记实现 CheckIn 方法;在这种情况下,我使用 2 种方法(第一种非常难看):
- I call c.CheckOut() before c.CheckIn(); this is very ugly, because you test 2 methods instead of one ... but I admit that I wrote something similar few times :-)
- I make the private setter protected, and I write a test class that inherits from the class under test; in this manner I can set the property to true before to call c.CheckIn() to ensure that the method is doing his job.
- 我在 c.CheckIn(); 之前调用 c.CheckOut(); 这非常难看,因为您测试了 2 种方法而不是一种方法……但我承认我写过几次类似的东西:-)
- 我保护了私有 setter,并编写了一个继承自被测类的测试类;通过这种方式,我可以在调用 c.CheckIn() 之前将该属性设置为 true,以确保该方法正在执行其工作。
Here it is the code:
这是代码:
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
}
}
Hope to help.
希望有所帮助。