Unit Testing: Moq doesn’t support property indexers
I hit a road block today writing some tests which were dependent upon another class’s property indexer. When trying to do the following using Moq:
1: [TestMethod]
2: public void Test1()
3: {
4: Mock<HttpContextBase> context = new Mock<HttpContextBase>();
5:
6: Object actual = null;
7:
8: context.ExpectSet(c => c.Session["SomeKey"]).Callback(o => actual = o);
9:
10: context.Object.Session["SomeKey"] = "some value";
11:
12: Assert.IsNotNull(actual, "Value was not set");
13: }
Line 8 fails with this error:
System.ArgumentException: Expression is not a property access: c => c.Session.get_Item("SomeKey").
It appears the current stable build of Moq (version 2.6.1014.1) doesn’t support property indexers. The good news is that a few days ago support was added for property indexers. However, if you’re like me and you’re not working with the latest and greatest, then there’s a workaround. Just create your own mock implementation of the class with the indexed property. In my case the class in question was HttpSessionStateBase. Here’s my mock implementation:
/// <summary>
/// Mock implementation of HttpSessionStateBase
/// </summary>
/// <remarks>
/// Current stable build of Moq (2.6.1014.1) doesn't support property indexers
/// at this time, so this is an implementation of HttpSessionStateBase
/// which allows us to verify that the session cache is being updated.
/// </remarks>
internal class MockSession : HttpSessionStateBase
{
Dictionary<string, object> session = new Dictionary<string, object>();
public override void Add(string name, object value)
{
session.Add(name, value);
}
public override object this[string name]
{
get
{
if (!session.ContainsKey(name))
return null;
return session[name];
}
set
{
session[name] = value;
}
}
}
Then you can do the following:
// setup
MockSession session = new MockSession();
Mock<HttpContextBase> context = new Mock<HttpContextBase>();
context.ExpectGet(c => c.Session).Returns(session);
// exercise
context.Session["SomeKey"] = "some value";
// assert
Assert.IsNotNull(context.Session["SomeKey"]);
Happy Moqing!
Labels: Moq, Unit Testing