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 context = new Mock();
 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) . The good news is that a few days ago support was added for property indexers

/// 
/// Mock implementation of HttpSessionStateBase
/// 
/// 
/// 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.
/// 
internal class MockSession : HttpSessionStateBase
{
 Dictionary session = new Dictionary();
 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 context = new Mock();
context.ExpectGet(c => c.Session).Returns(session);
// exercise
context.Session["SomeKey"] = "some value";
// assert
Assert.IsNotNull(context.Session["SomeKey"]);

Happy Moqing!