Дразнящие коллекции с Rhino Mocks - PullRequest
2 голосов
/ 28 октября 2010

Так что, думаю, многие люди хотят сделать это, издеваться над коллекцией. В прошлом с Rhino я делал это с чем-то вроде:

var col_mock = MockRepository.GenerateMock<ICustomCollection>(); // returns ICustom let's say
List<ICustom> col_real = new List<ICustom>();
col_real.Add(custom_mock1);
col_real.Add(custom_mock2);
col_real.Add(custom_mock3);
col_mock.Stub(x => x.GetEnumerator()).Return(col_real.GetEnumerator());

Так что да, это работает нормально, когда вы передаете col_mock, вы получаете возвращенные объекты (custom_mock1 и т. Д.). Большой! Мы успешно смоделировали пользовательскую коллекцию, используя типизированный список для хранения загруженных объектов.

Проблема в том, что вы можете сделать это только один раз! вы можете проповедовать эту коллекцию только один раз. Кто-нибудь знает (не создавая фактическую пользовательскую коллекцию ...), как я могу добиться макета пользовательской коллекции, которую можно повторять более одного раза?

Ответы [ 2 ]

8 голосов
/ 28 октября 2010

Проблема в том, что перечислитель создается только один раз, когда вы вызываете Return. Затем он возвращает тот же экземпляр, который уже находится в конце списка после первого foreach.

Вам нужно создавать новый перечислитель каждый раз, когда вызывается GetEnumerator. Вы можете использовать WhenCalled для этого.

Return все еще нужен, потому что Rhino Mocks будет жаловаться, когда он пропадет. Но не имеет значения, что вы передаете в качестве аргумента.

[TestMethod]
public void GetEnumerator()
{
    IList<int> col_mock = MockRepository.GenerateMock<IList<int>>();
    List<int> col_real = new List<int>();
    col_real.Add(1);
    col_real.Add(2);
    col_real.Add(3);
    col_mock
        .Stub(x => x.GetEnumerator())
        // create new enumerator instance for each call
        .WhenCalled(call => call.ReturnValue = col_real.GetEnumerator())
        .Return(null) // is ignored, but needed for Rhinos validation
        .Repeat.Any();

    foreach (int i in col_mock)
    {
    }

    int count = 0;
    foreach (int i in col_mock)
    {
        count++;
    }
    Assert.AreSame(3, count);
}
4 голосов
/ 28 октября 2010

Так что, думаю, многие люди хотят сделать это, издеваться над коллекцией.

На самом деле нет.Смысл насмешливого в том, чтобы быстро вызвать в воображении объект с определенным интерфейсом и поведением, которое вы полностью контролируете, чтобы вы могли использовать тестируемый класс.

Но в случае, когда вам нужен ICollection<Foo>, вы можете просто создать экземпляр List<Foo>.Вы можете заполнить список в своем модульном тесте любым способом;у вас уже есть полный контроль.

Или предположим, что вам нужен IEnumerable<Foo> с более интересным поведением, которое вы не можете создать с помощью списка, например, бесконечное перечислимое или перечислимое, которое создает исключения.Это можно сделать, определив метод итератора в вашем классе модульного теста с ключевым словом yield.Опять же, издеваться не нужно.

...