Подделка перечислителя в FakeItEasy - PullRequest
3 голосов
/ 02 марта 2011

Как создать фальшивку с 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

Ответы [ 2 ]

6 голосов
/ 02 марта 2011

Я не совсем уверен, что понимаю, что вы имеете в виду, код, который вы предоставили, всегда будет неудачным.Однако, если вы хотите сказать, что хотите вернуть 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 не использует модель записи / воспроизведения, и вы правы в том, что последнее настроенное правило имеет приоритет над любыми ранее указанными правилами.Вот почему вы должны указать repeat - ".Once ()" - в последней конфигурации, чтобы она действовала только один раз.

Существует множество причин, по которым последняя имеет приоритет, одна из самых важных -то, что он позволяет вам установить возвращаемое значение по умолчанию в настройках вашего прибора и переопределить его, чтобы возвращать определенные значения в некоторых ваших тестах, это невозможно при использовании модели записи / воспроизведения.

0 голосов
/ 03 апреля 2015

Пример ОП, основанный на ответе Патрика, хорош ... но утомителен, если последовательность увеличивается. В дополнение к этому ответу учтите, что хотя примеры с фальшивкой / имитацией чаще всего показывают кучу прямого кода для самоорганизации, на самом деле вы обладаете всей мощью языка программирования в вашей команде. Условные выражения, циклы и даже процедуры.

Итак, рассмотрим следующее:

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> один статический универсальный метод мог бы использоваться для целой группы различных перечислителей.)

...