Использование Moq для установки индексаторов в С#
Мне трудно понять, как установить indexers в С# с помощью Moq. Документация Moq слаба, и я много раз искал... то, что я хотел бы сделать, аналогично в решении Как Moq Установка свойства Indexed:
var someClass = new Mock<ISomeClass>();
someClass.SetupSet(o => o.SomeIndexedProperty[3] = 25);
Я хочу изменить выше, чтобы работать для любого индекса и любого значения, поэтому я могу просто сделать что-то вроде этого:
someClass.Object.SomeIndexedProperty[1] = 5;
В настоящее время у меня есть следующее, которое отлично работает для индексатора с индексированным свойством, но если я когда-либо установил значение 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]);
Ответы
Ответ 1
Я нашел решение своей проблемы. Это требует сдвига в моем мышлении... Я искал использовать NUnit Assert
, чтобы проверить, что установщик индексатора в моем макете someClass
вызывался с правильным значением.
Кажется, что с помощью Moq поддерживаемый способ сделать это - использовать функцию VerifySet
. Надуманный пример:
someClass.Object.SomeIndexedProperty[3] = 25;
someClass.VerifySet(mock => mock.SomeIndexedProperty[3] = 25);
Пропуск unit test, так как SomeIndexedProperty[3]
установлен в 25, но в противном случае не будет.
Ответ 2
Использование 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
В вашем тесте ваши единственные установленные ожидания для getter индексатора - и это всегда будет возвращать соответствующее значение из вашего массива. Индексатор не ведет себя как настоящая вещь. Вы можете попробовать несколько вещей, чтобы исправить это:
-
Вы можете проверить, не заблокирован ли этот индекс. Я лично использую RhinoMocks, поэтому я понятия не имею, реализовано ли это
someClass.SetupProperty(f => f.SomeIndexedProperty);
-
Вы также можете попытаться издеваться над установщиком и заставить его изменить базовый массив. Мое первое предположение заключалось в том, чтобы попробовать что-то в этом направлении (без гарантии, что он будет работать):
someClass.Setup(o => o.SomeIndexedProperty[It.IsAny<int>()] = It.IsAny<int>())
.Callback((index, value) => someValues[index] = value);
-
Или, если интерфейс ISomeClass достаточно мал, вы могли бы просто создать реализацию-заглушку самостоятельно (что бы реализовать индексатор как словарь, массив и т.д.)