Estoy intentando simular una llamada a una propiedad indexada. Es decir, me gustaría moq lo siguiente:
object result = myDictionaryCollection["SomeKeyValue"];
y también el valor del setter
myDictionaryCollection["SomeKeyValue"] = myNewValue;
Hago esto porque necesito burlarme de la funcionalidad de una clase que usa mi aplicación.
¿Alguien sabe cómo hacer esto con MOQ? Probé variaciones de lo siguiente:
Dictionary<string, object> MyContainer = new Dictionary<string, object>();
mock.ExpectGet<object>( p => p[It.IsAny<string>()]).Returns(MyContainer[(string s)]);
Pero eso no se compila.
¿Es posible lo que estoy tratando de lograr con MOQ? ¿Alguien tiene algún ejemplo de cómo puedo hacerlo?
Respuestas:
No está claro lo que está tratando de hacer porque no muestra la declaración del simulacro. ¿Estás intentando burlarte de un diccionario?
MyContainer[(string s)]
no es válido C #.Esto compila:
var mock = new Mock<IDictionary>(); mock.SetupGet( p => p[It.IsAny<string>()]).Returns("foo");
fuente
SetupSet
lugar deExpectGet
. también funciona para setters.Ash, si quieres tener una sesión HTTP simulada, entonces este fragmento de código hace el trabajo:
/// <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); } }
fuente
TestSuiteBase
una biblioteca o tu propia clase?A medida que ha detectado correctamente, hay métodos distintos
SetupGet
ySetupSet
para inicializar captadores y definidores, respectivamente. AunqueSetupGet
está destinado a ser utilizado para propiedades, no para indexadores, y no le permitirá manejar la clave que se le pasa. Para ser precisos, los indexadoresSetupGet
llamarán deSetup
todos modos: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); ... } ... }
Para responder a su pregunta, aquí hay una muestra de código que usa subyacente
Dictionary
para almacenar valores: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 value) => dictionary[key] = value);
Como puede ver, debe especificar explícitamente la clave para configurar el definidor del indexador. Los detalles se describen en otra pregunta SO: Moq una propiedad indexada y use el valor del índice en la devolución / devolución de llamada
fuente
No es tan difícil, pero me tomó un poco encontrarlo :)
var request = new Moq.Mock<HttpRequestBase>(); request.SetupGet(r => r["foo"]).Returns("bar");
fuente
Parece que lo que estaba intentando hacer con MOQ no es posible.
Básicamente, estaba intentando MOQ un objeto de tipo HTTPSession, donde la clave del elemento que se establece en el índice solo se puede determinar en tiempo de ejecución. Se necesita acceso a la propiedad indexada para devolver el valor que se estableció previamente. Esto funciona para índices basados en números enteros, pero los índices basados en cadenas no funcionan.
fuente