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