Как 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, есть ли у кого-нибудь примеры того, как я могу это сделать?
Ответы
Ответ 1
Похоже, что то, что я пытаюсь сделать с MOQ, невозможно.
По сути, я пытался MOQ создать объект типа HTTPSession, где ключ элемента, установленного в индекс, может быть определен только во время выполнения. Доступ к индексированному свойству должен был вернуть значение, которое было ранее установлено. Это работает для индексов, основанных на целых числах, но индексы на основе строк не работают.
Ответ 2
Непонятно, что вы пытаетесь сделать, потому что вы не показываете объявление макета. Вы пытаетесь издеваться над словарем?
MyContainer[(string s)]
недействителен С#.
Это компилируется:
var mock = new Mock<IDictionary>();
mock.SetupGet( p => p[It.IsAny<string>()]).Returns("foo");
Ответ 3
Ясень, если вы хотите, чтобы 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);
}
}
Ответ 4
Это не так сложно, но потребовалось немного, чтобы найти его:)
var request = new Moq.Mock<HttpRequestBase>();
request.SetupGet(r => r["foo"]).Returns("bar");
Ответ 5
Как вы правильно заметили, существуют различные методы 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);
Как вы можете видеть, вам нужно явно указать ключ для настройки установщика индексатора. Подробности описаны в другом вопросе SO: Moq индексированное свойство и используйте значение индекса в обратном/обратном вызове