How to MOQ an Indexed property
Solution 1:
It's not clear what you're trying to do because you don't show the declaration of the mock. Are you trying to mock a dictionary?
MyContainer[(string s)]
isn't valid C#.
This compiles:
var mock = new Mock<IDictionary>();
mock.SetupGet( p => p[It.IsAny<string>()]).Returns("foo");
Solution 2:
Ash, if you want to have HTTP Session mock, then this piece of code does the job:
/// <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);
}
}
Solution 3:
As you correctly spotted, there are distinct methods SetupGet
and SetupSet
to initialize getters and setters respectively. Although SetupGet
is intended to be used for properties, not indexers, and will not allow you handling key passed to it. To be precise, for indexers SetupGet
will call Setup
anyway:
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);
...
}
...
}
To answer your question, here is a code sample using underlying Dictionary
to store values:
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);
As you can see, you have to explicitly specify key to set up indexer setter. Details are described in another SO question: Moq an indexed property and use the index value in the return/callback
Solution 4:
Its not that difficult but it took a little bit to find it :)
var request = new Moq.Mock<HttpRequestBase>();
request.SetupGet(r => r["foo"]).Returns("bar");