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