Использование Moq для установки индексаторов в C # - PullRequest
19 голосов
/ 27 мая 2010

У меня проблемы с выяснением, как установить индексаторы в C # с помощью Moq. Документация Moq слабая, и я много занимался поиском ... что я хотел бы сделать, это похоже на решение Как Moq Установка индексированного свойства :

var someClass = new Mock<ISomeClass>();
someClass.SetupSet(o => o.SomeIndexedProperty[3] = 25);

Я хочу изменить вышеприведенное для работы с любым индексом и любым значением, чтобы я мог просто сделать что-то вроде этого:

someClass.Object.SomeIndexedProperty[1] = 5;

В настоящее время у меня есть следующее, которое отлично работает для индексированного свойства get, но если я когда-либо установлю значение, Moq игнорирует его:

var someValues = new int[] { 10, 20, 30, 40 };
var someClass = new Mock<ISomeClass>();
someClass.Setup(o => o.SomeIndexedProperty[It.IsAny<int>()])
    .Returns<int>(index => someValues[index]);

// Moq doesn't set the value below, so the Assert fails!
someClass.Object.SomeIndexedProperty[3] = 25;
Assert.AreEqual(25, someClass.Object.SomeIndexedProperty[3]);

Ответы [ 3 ]

11 голосов
/ 27 мая 2010

Я нашел решение своей проблемы. Это требует изменения в моем мышлении ... Я искал NUnit Assert, чтобы убедиться, что установщик индексатора в моем someClass макете вызывался с правильным значением.

Похоже, что с Moq поддерживаемый способ сделать это - использовать функцию VerifySet. Придуманный пример:

someClass.Object.SomeIndexedProperty[3] = 25;
someClass.VerifySet(mock => mock.SomeIndexedProperty[3] = 25);

Юнит-тестирование проходит, поскольку SomeIndexedProperty[3] установлено на 25, но в противном случае не будет выполнено.

5 голосов
/ 27 ноября 2010

Использование Moq 3.1.416.3

Настройка не будет работать для индексаторов (поскольку она принимает выражение, означающее, что операторы присваивания исключены)

, поэтому вам нужно использовать SetupSet, как

_settingsStore.SetupSet(store => store["MruNotes"] = It.IsAny<string>())
                .Callback<string,string>( (key, value) => persistedValue = value);

Небольшое предостережение: это выражение соответствует, только если ключ "MruNotes". Я не смог использовать такой ключ как It.IsAny для ключа.

3 голосов
/ 27 мая 2010

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

  1. Вы можете проверить, можете ли вы заглушить этот индексатор. Я лично использую RhinoMocks, поэтому я не знаю, реализовано ли это

    someClass.SetupProperty(f => f.SomeIndexedProperty);
    
  2. Вы также можете попробовать смоделировать сеттер и изменить его основной массив. Моим первым предположением было бы попробовать что-то в этом роде (нет гарантии, что это сработает):

    someClass.Setup(o => o.SomeIndexedProperty[It.IsAny<int>()] = It.IsAny<int>())
    .Callback((index, value) => someValues[index] = value);
    
  3. Или, если интерфейс ISomeClass достаточно мал, вы можете просто создать реализацию-заглушку (в которой индексатор будет реализован как словарь, массив и т. Д.)

...