Там есть ряд причин, почему я советовал бы против него. Во-первых, как упоминалось в комментариях, нет причин, по которым настоящий словарь не будет работать здесь. We shouldn't mock types that what we don't own и only mock types we do own.
Линия _mockContext.SetupGet(m => m.InstanceVariables[It.IsAny<string>()]).Returns(@"c:\users\randomplace");
пытается высмеять Get
на Dictionary<T, T>
, который как примечания @RB не virtual
, следовательно, ваша ошибка. Возможно, вы насмехаетесь над своим интерфейсом, но настроенный там на .NET.
Во-вторых, IMO, It.IsAny<string>()
приводит к довольно слабым испытаниям, потому что он будет отвечать на любые строки. Структурирование что-то вроде:
const string MyKey = "someKey";
var dictionary = new Dictionary<string, object>();
dictionary.Add(MyKey, @"c:\users\randomplace");
_mockContext.Setup(m => m.InstanceVariables).Returns(dictionary);
var sut = new SomeObject(_mockContext.Object());
var result = sut.Act(MyKey);
// Verify
будет сильнее, как словарь может реагировать только с пути, если правильный ключ дается/или сгенерирован вашей системой проверяемого (SUT).
Тем не менее, если вы абсолютно необходимо издеваться словарь, по причинам, которые не видны на вопрос ... то свойство на вашем интерфейсе должен быть интерфейс для словаря, IDictionary
, не класс бетона:
IDictionary<string, object> InstanceVariables { get; set; }
Тогда вы можете создать словарь макет с помощью:
var dictionary = new Mock<IDictionary<string, object>>();
dictionary.SetupGet(d => d[It.IsAny<string>()]).Returns(@"c:\users\randomplace");
Затем в контекстном издеваться:
_mockContext.SetupGet(d => d.InstanceVariables).Returns(dictionary.Object);
Почему нужно быть Virtual?
Moq and other similar mocking frameworks can only mock interfaces, abstract methods/properties (on abstract classes) or virtual methods/properties on concrete classes.
This is because it generates a proxy that will implement the interface or create a derived class that overrides those overrideable methods in order to intercept calls.
Credit to @aqwert
Зачем вам нужно издеваться над «Словарем», если вы можете создать словарь для всех необходимых полей? – Valentin
Поскольку я хочу изменить то, что появляется в экземпляре InstanceVariables, когда я выполняю метод, который я передал в моем объекте mockContext, в –
. Ваша собственность - это словарь, а не 'IDictionary'. Поэтому, чтобы скомпилировать его, вы должны высмеивать конкретную реализацию, * не * интерфейс, как вы заявляете (хотя я точно не знаю, как вы не отправляли этот код). Следовательно, ошибка правильная - вы не можете переопределить не виртуальный член (а индексный словарь не является виртуальным).Тем не менее, вопрос @ Valentin все еще стоит - почему бы просто не создать словарь со значениями, установленными по вашему желанию для вашего модульного теста, - словарь - это немой магазин данных - там нет функциональности, чтобы издеваться! –