在 FakeItEasy 中伪造一个枚举器
如何使用 FakeItEasy 创建一个允许在连续调用时返回不同值的假值。这是我希望能够做的一个示例:
var enumerator = A.Fake<IDictionaryEnumerator>();
A.CallTo(() => enumerator.MoveNext()).Returns(true); //Expected value for first call
A.CallTo(() => enumerator.Key).Returns("key1");
A.CallTo(() => enumerator.Value).Returns("value1");
A.CallTo(() => enumerator.MoveNext()).Returns(false); //Expected value for second call
Assert.IsTrue(enumerator.MoveNext()); //Fails
Assert.IsFalse(enumerator.MoveNext());
断言将失败,因为 MoveNext 的最后一次设置将覆盖第一个设置。
是否可以在 FakeItEasy 中执行我想要的操作?
。
[编辑]
澄清了原始问题的示例并在下面提供了一个工作示例。
根据帕特里克的回答,此代码显示了如何设置假的。诀窍是反转所有设置并使用 Once()
。
var enumerator = A.Fake<IDictionaryEnumerator>();
A.CallTo(() => enumerator.MoveNext()).Returns(false).Once();
A.CallTo(() => enumerator.MoveNext()).Returns(true).NumberOfTimes(2);
A.CallTo(() => enumerator.Key).Returns("key2").Once();
A.CallTo(() => enumerator.Value).Returns("value2").Once();
A.CallTo(() => enumerator.Key).Returns("key1").Once();
A.CallTo(() => enumerator.Value).Returns("value1").Once();
while(enumerator.MoveNext())
{
Debug.WriteLine(enumerator.Key + ": "+ enumerator.Value);
}
这将打印:
key1: value1
key2: value2
How can I create a fake with FakeItEasy that allows different return values on successive calls. This is one example of what I would like to be able to do:
var enumerator = A.Fake<IDictionaryEnumerator>();
A.CallTo(() => enumerator.MoveNext()).Returns(true); //Expected value for first call
A.CallTo(() => enumerator.Key).Returns("key1");
A.CallTo(() => enumerator.Value).Returns("value1");
A.CallTo(() => enumerator.MoveNext()).Returns(false); //Expected value for second call
Assert.IsTrue(enumerator.MoveNext()); //Fails
Assert.IsFalse(enumerator.MoveNext());
The assertion will fail since it the last set up of MoveNext will overwrite the first one.
Is it possible to do what I want in FakeItEasy?
.
[Edit]
Clarified the original question's example and provided a working example below.
Based on Patrik's answer this code shows how you can set up the fake. The trick is to reverse all setups and use Once()
.
var enumerator = A.Fake<IDictionaryEnumerator>();
A.CallTo(() => enumerator.MoveNext()).Returns(false).Once();
A.CallTo(() => enumerator.MoveNext()).Returns(true).NumberOfTimes(2);
A.CallTo(() => enumerator.Key).Returns("key2").Once();
A.CallTo(() => enumerator.Value).Returns("value2").Once();
A.CallTo(() => enumerator.Key).Returns("key1").Once();
A.CallTo(() => enumerator.Value).Returns("value1").Once();
while(enumerator.MoveNext())
{
Debug.WriteLine(enumerator.Key + ": "+ enumerator.Value);
}
This will print:
key1: value1
key2: value2
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我不完全确定我理解你的意思,你提供的代码总是会失败。但是,如果您的意思是希望它在调用时第二次返回 true,则可以完成。我可以想到几种不同的方法,其中两种是:
另一种方法是:
编辑:
第二,虽然我想我更好地理解你的问题,但你想要发生的是MoveNext 第一次应该返回 true,第二次返回 false?如果是这种情况,只需更改上面示例中值的顺序即可。
FakeItEasy 不使用记录/重播模型,您是正确的,因为最新配置的规则优先于任何早期指定的规则。这就是为什么您必须在最新配置上指定重复“.Once()”,使其仅有效一次。
最新优先的原因有很多,最重要的原因之一是它允许您在夹具的设置中设置默认返回值,并覆盖它以在某些测试中返回特定值,这在以下情况下是不可能的:使用记录/重放模型。
I'm not entirely sure that I understand what you mean, the code you supplied will always fail. However if you mean that you want it to return true the second time it's called it can be done. There are a couple of different ways that I can think of, two of them are:
The other way is:
Edit:
On second though I guess I understand your question better, what you want to happen is that MoveNext should return true the first time and false the second time? If that's the case just change the orders of the values in the examples above.
FakeItEasy does not use a record/replay model and you are correct in that the latest configured rule has precedence over any earlier specified rules. That's why you have to specify repeat - ".Once()" - on the latest configuration for it only to be valid once.
There are many reasons why the latest has precedence, one of the most important ones is that it lets you set up a default return value in the setup of your fixture and override it to return specific values in some of your tests, this is impossible when using a record/replay model.
OP 基于帕特里克答案的示例很好......但如果序列变大,就会很乏味。为了补充这个答案,请考虑即使假/模拟示例通常显示一堆直线代码来自行排列,但您实际上拥有编程语言的全部功能。条件、循环,甚至过程。
因此,请考虑以下内容:
现在测试变为:(
IDictionaryEnumerator
成对处理,因此此示例并不明显有益。对于标准IEnumerator< /code> 一个静态泛型方法可以为一大堆不同的枚举器服务。)
The OP's example based on Patrik's answer is fine ... but tedious if the sequence grows large. To supplement that answer consider that even though fake/mock examples most often show a bunch of straight line code to Arrange themselves you actually have the full power of a programming language at your command. Conditionals, loops, and even procedures.
So consider the following:
and now the test becomes:
(An
IDictionaryEnumerator
deals in pairs, so this example isn't as clearly beneficial as it could be. For a standardIEnumerator<T>
a single static generic method would serve for a whole bunch of different enumerators.)