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
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.