5

I'm having problems returning a Session value set from mocking using Moq. Using the following

public class TestHelpers
{
 public long sessionValue = -1;
 public HttpContextBase FakeHttpContext()
 {

  var httpContext = new Mock<HttpContextBase>();
  var session = new Mock<HttpSessionStateBase>();
  httpContext.Setup(x => x.Session).Returns(session.Object);
  httpContext.SetupGet(x => x.Session["id"]).Returns(sessionValue);
  httpContext.SetupSet(x => x.Session["id"] = It.IsAny<long>())
        .Callback((string name, object val) =>
        {
           sessionValue = (long)val;
        });
  }
}

When I try to obtain the value outside using

var th = new TestHelpers();
HttpContextBase httpContext = th.FakeHttpContext();

do some stuff that sets Session["id"]

var sessionid = httpContext.Session["id"];

sessionid turns out to be -1. But I can obtain the set session value using

th.sessionValue

What's wrong? Can't I simply return the set value via Moq?

sean
  • 11,164
  • 8
  • 48
  • 56

4 Answers4

11

I need to stop answering my own questions. It turns out that I needed to mock Session["id"] again like so ...

httpContext.SetupSet(x => x.Session["id"] = It.IsAny<long>())
        .Callback((string name, object val) =>
        {
           sessionValue = (long)val;
           httpContext.SetupGet(x => x.Session["id"]).Returns(sessionValue);
        });
sean
  • 11,164
  • 8
  • 48
  • 56
  • This did not work for me: @Konamimam appears to be correct that the .Callback does not get fired. The correct approach seems to be here: http://stackoverflow.com/a/2921695/213609 – Stelloy May 10 '13 at 15:17
2

Moq's Setup methods do not work with indexed properties that have string indexes. See here: How to MOQ an Indexed property

Johnny
  • 8,939
  • 2
  • 28
  • 33
Konamiman
  • 49,681
  • 17
  • 108
  • 138
1

I just spent long time trying to figure out the easiest way to do it with moq, below is a copy past of my code that actually worked for me :

var _adminctrl = new Moq.Mock<AdminController>(); //AdminController is my MVC controller

var mock = new Mock<ControllerContext>();
mock.Object.Controller = _adminctrl.Object;
mock.Setup(p => p.HttpContext.Session["UserInfoKey"]).Returns(new ViewModel());
 //here is the catch, attaching the ControllerContext to your controller
_adminctrl.Object.ControllerContext = mock.Object;

hope this helps!

Adam
  • 3,815
  • 29
  • 24
1

It's because you're returning the value in the getter which was passed by value. So everytime you invoke the getter, you get the same value returned.

Change the Returns() to use a delegate so it is evaluated every time. That way you will get the correct value every time :)

Much easier on the eye than a SetupGet embedded inside a SetupSet.

httpContext.SetupSet(x => x.Session["id"] = It.IsAny<long>())
        .Callback((string name, object val) => sessionValue = (long)val);
httpContext.SetupGet(x => x.Session["id"]).Returns(() => sessionValue);
stoj
  • 1,116
  • 1
  • 14
  • 25