Как MOQ индексированное свойство
Я пытаюсь издеваться над вызовом индексированного свойства. Т. е. я хотел бы moq следующее:
object result = myDictionaryCollection["SomeKeyValue"];
а также Значение сеттера
myDictionaryCollection["SomeKeyValue"] = myNewValue;
Я делаю это, потому что мне нужно издеваться над функциональностью класса, который использует мое приложение.
кто-нибудь знает, как это сделать с MOQ? Я пробовал вариации на следующие темы:
Dictionary<string, object> MyContainer = new Dictionary<string, object>();
mock.ExpectGet<object>( p => p[It.IsAny<string>()]).Returns(MyContainer[(string s)]);
но это не компиляции.
Это то, что я пытаюсь достичь возможно с MOQ, делает у кого-нибудь есть примеры того, как я могу это сделать?
5 ответов:
неясно, что вы пытаетесь сделать, потому что вы не показываете объявление макета. Вы пытаетесь издеваться над словарем?
MyContainer[(string s)]
недопустимый C#.Это компилирует:
var mock = new Mock<IDictionary>(); mock.SetupGet( p => p[It.IsAny<string>()]).Returns("foo");
Эш, если вы хотите иметь http-сессии макет, то этот кусок кода делает работу:
/// <summary> /// HTTP session mockup. /// </summary> internal sealed class HttpSessionMock : HttpSessionStateBase { private readonly Dictionary<string, object> objects = new Dictionary<string, object>(); public override object this[string name] { get { return (objects.ContainsKey(name)) ? objects[name] : null; } set { objects[name] = value; } } } /// <summary> /// Base class for all controller tests. /// </summary> public class ControllerTestSuiteBase : TestSuiteBase { private readonly HttpSessionMock sessionMock = new HttpSessionMock(); protected readonly Mock<HttpContextBase> Context = new Mock<HttpContextBase>(); protected readonly Mock<HttpSessionStateBase> Session = new Mock<HttpSessionStateBase>(); public ControllerTestSuiteBase() : base() { Context.Expect(ctx => ctx.Session).Returns(sessionMock); } }
как вы правильно заметили, есть различные способы
SetupGet
иSetupSet
для инициализации геттеров и сеттеров соответственно. ХотяSetupGet
предназначен для использования для свойств, а не индексаторов, и не позволит вам обрабатывать ключ, переданный ему. Точнее, для индексаторовSetupGet
будем называтьSetup
в любом случае:internal static MethodCallReturn<T, TProperty> SetupGet<T, TProperty>(Mock<T> mock, Expression<Func<T, TProperty>> expression, Condition condition) where T : class { return PexProtector.Invoke<MethodCallReturn<T, TProperty>>((Func<MethodCallReturn<T, TProperty>>) (() => { if (ExpressionExtensions.IsPropertyIndexer((LambdaExpression) expression)) return Mock.Setup<T, TProperty>(mock, expression, condition); ... } ... }
чтобы ответить на ваш вопрос, вот пример кода с использованием базовых
Dictionary
для сохранения значений:var dictionary = new Dictionary<string, object>(); var applicationSettingsBaseMock = new Mock<SettingsBase>(); applicationSettingsBaseMock .Setup(sb => sb[It.IsAny<string>()]) .Returns((string key) => dictionary[key]); applicationSettingsBaseMock .SetupSet(sb => sb["Expected Key"] = It.IsAny<object>()) .Callback((string key, object vaue) => dictionary[key] = vaue);
как вы можете видеть, вы должны явно укажите ключ для настройки индексатора setter. Подробности описаны в другом вопрос: Moq индексированное свойство и использовать значение индекса в return / callback
ее не так сложно, но потребовалось немного, чтобы найти его :)
var request = new Moq.Mock<HttpRequestBase>(); request.SetupGet(r => r["foo"]).Returns("bar");
похоже, что то, что я пытался сделать с MOQ, невозможно.
по существу, я пытался MOQ объект типа HTTPSession, где ключ элемента, установленного в индекс, может быть определен только во время выполнения. Доступ к индексированному свойству необходим для возврата ранее заданного значения. Это работает для целых индексов, но строковые индексы не работают.