3

如何使用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中做我想做的事?

.

[编辑]
澄清了原始问题的示例,并在下面提供了一个工作示例。

根据 Patrik 的回答,此代码显示了如何设置假货。诀窍是反转所有设置并使用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
4

2 回答 2

6

我不完全确定我理解你的意思,你提供的代码总是会失败。但是,如果您的意思是希望它在第二次调用时返回 true,则可以完成。我能想到几种不同的方法,其中两种是:

A.CallTo(() => enumerator.MoveNext()).ReturnsNextFromSequence(false, true);

另一种方式是:

A.CallTo(() => enumerator.MoveNext()).Returns(true);
A.CallTo(() => enumerator.MoveNext()).Returns(false).Once();

编辑:

第二,虽然我想我更好地理解你的问题,但你想要发生的是 MoveNext 应该第一次返回 true 而第二次返回 false ?如果是这种情况,只需更改上面示例中值的顺序即可。

FakeItEasy 不使用记录/重放模型,您是正确的,最新配置的规则优先于任何先前指定的规则。这就是为什么您必须在最新配置上指定重复 - ".Once()" - 以使其仅有效一次。

最新的有优先权的原因有很多,最重要的原因之一是它允许您在夹具设置中设置默认返回值并覆盖它以在某些测试中返回特定值,这是不可能的使用记录/重放模型。

于 2011-03-02T20:54:55.137 回答
0

基于 Patrik 回答的 OP 示例很好……但如果序列变大,则很乏味。为了补充这个答案,请考虑即使假/模拟示例最常显示一堆直线代码来安排自己,您实际上拥有编程语言的全部功能。条件、循环甚至过程。

所以考虑以下几点:

public static void AFakeDictionaryEnumeratorReturns(
                       IDictionaryEnumerator enumerator, params object[] pairs)
{
    if (0 != pairs.Length % 2)
        throw new ArgumentException("pairs must have even number of elements", "pairs");

    int n = pairs.Length / 2;

    A.CallTo(() => enumerator.MoveNext()).Returns(false).Once();
    A.CallTo(() => enumerator.MoveNext()).Returns(true).NumberOfTimes(n);

    for (int i = pairs.Length; i > 0; i -= 2)
    {
        A.CallTo(() => enumerator.Key).Returns(pairs[i - 2]).Once();
        A.CallTo(() => enumerator.Value).Returns(pairs[i - 1]).Once();
    }
}

现在测试变成:

var enumerator = A.Fake<IDictionaryEnumerator>();
AFakeDictionaryEnumeratorReturns(enumerator, 
                                 "key1", "value1", "key2", "value2", "key3", "value3");

var keys = new List<object>();
var values = new List<object>();
while (enumerator.MoveNext())
{
    keys.Add(enumerator.Key);
    values.Add(enumerator.Value);
}

Assert.Equal(new List<object> { "key1", "key2", "key3" }, keys);
Assert.Equal(new List<object> { "value1", "value2", "value3" }, values);

IDictionaryEnumerator成对交易,所以这个例子并不像它可能的那样明显有益。对于标准IEnumerator<T>,单个静态泛型方法将服务于一大堆不同的枚举器。)

于 2015-04-02T22:14:01.297 回答