verifiable setup property mock examples dotnet c# tdd mocking moq

c# - setup - Cómo MOQ una propiedad indexada



setup mock (5)

Estoy intentando burlar una llamada a una propiedad indexada. Es decir, me gustaría consultar lo siguiente:

object result = myDictionaryCollection["SomeKeyValue"];

y también el valor del colocador

myDictionaryCollection["SomeKeyValue"] = myNewValue;

Estoy haciendo 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 en 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 compila.

Es lo que intento lograr con MOQ, ¿alguien tiene algún ejemplo de cómo puedo hacer esto?


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 estaba configurando en el índice solo podía determinarse en tiempo de ejecución. El acceso a la propiedad indexada es necesario para devolver el valor que se estableció previamente. Esto funciona para índices basados ​​en enteros, pero los índices basados ​​en cadenas no funcionan.


Ash, si quieres que la sesión HTTP se simule, entonces esta parte del 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); } }


No es tan difícil, pero tardó un poco en encontrarlo :)

var request = new Moq.Mock<HttpRequestBase>(); request.SetupGet(r => r["foo"]).Returns("bar");


No está claro lo que estás tratando de hacer porque no muestras 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");


Como correctamente detectó, hay distintos métodos SetupGet y SetupSet para inicializar getters y setters, respectivamente. Aunque SetupGet está destinado a ser usado para propiedades, no para indexadores, y no le permitirá manejar claves pasadas a él. Para ser precisos, para los indexadores SetupGet llamará a la Setup 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 un ejemplo de código que utiliza el Dictionary subyacente 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 vaue) => dictionary[key] = vaue);

Como puede ver, debe especificar explícitamente la clave para configurar el indexador setter. Los detalles se describen en otra pregunta de SO: Moq una propiedad indexada y usa el valor de índice en la devolución / devolución de llamada