Используя Moq для установки индексаторов в C#

Я испытываю затруднения при выяснении, как установить индексаторы в 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]);

19
задан Community 23 May 2017 в 11:53
поделиться

2 ответа

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

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

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

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

11
ответ дан 30 November 2019 в 04:52
поделиться

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

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

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

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

3
ответ дан 30 November 2019 в 04:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: