1

I have a function which based on some internal logic, stores a redirect string in a session variable (Redirect_To). I am trying to write a unit test which checks the value of this session variable once the action called has completed.

I am using Moq to mock up some of my properties and functions. However, whenever I set the Session variable (Redirect_To) up with Moq, it must set it as read only because I can no longer assign a value to it which leads my unit test to fail.

Here is my unit test:

 public async Task Index_ClientTypeIsRPI_ExpectCorrectRedirect()
    {
        var sessionDict = new Dictionary<string, string>
    {
        {"CID", "124" },
        {"UserName", "AK92630" },
        {"REDIRECT_TO", "www.google.com" }
    };

        var controllerContext = HttpContextManager.ReturnMockControllerContextWithSessionVars(sessionDict);

        var mockIdentity = new Mock<IIdentity>();

        mockIdentity.Setup(x => x.Name).Returns("TestName");
        controllerContext.Setup(x => x.HttpContext.User.Identity).Returns(mockIdentity.Object);
        controllerContext.Setup(x => x.HttpContext.User.IsInRole(UserLevel.Subrep.GetDescription())).Returns(true);
        controllerContext.Setup(x => x.HttpContext.Request.Browser.Browser).Returns("InternetExplorer");
        _controller.ControllerContext = controllerContext.Object;
        _iMockManifestManager.Setup(x => x.ReturnSingleMainDataRecordViaTransNoCIDAndUserNameAsync(It.IsAny<string>, It.IsAny<string>, It.IsAny<string>)).ReturnsAsync(New MainData());

        var transNo = "Asdf";
        await _controller.Index(transNo, true, "sd", "dg");

        Assert.AreEqual("www.facebook.com", _controller.HttpContext.Session["REDIRECT_TO"]);
    }

ReturnMockControllerContextWithSessionVars (Function which sets my session variables)

internal static Mock<ControllerContext> ReturnMockControllerContextWithSessionVars(Dictionary<string, object> sessionKeysAndValues):
{
    var fakeHttpContext = HttpContextManager.CreateLocalAuthenticatedUserWithMockHttpContext();
    var controllerContext = new Mock<ControllerContext>;
    controllerContext.Setup(x => x.HttpContext).Returns(fakeHttpContext.Object);
    foreach (var item in sessionKeysAndValues)
    {
        controllerContext.Setup(x => x.HttpContext.Session[item.Key]).Returns(item.Value);
    }

    return controllerContext;
}

Action:

public async Task Index(string transNo, bool? isRechase, string clientID, string clientType)
{
    switch (clientType.ToUpper())
    {
        case "RPI":
            Session["REDIRECT_TO"] = "www.reddit.com";
        break;
        case "LM":
            Session["REDIRECT_TO"] = "www.bbc.co.uk";
        default:
            Session["REDIRECT_TO"] = "www.stackoverflow.com";
            break;
    }

    //Do async stuff

    return null;

}

Does anyone know how to change my code so when I setup Session["Redirect_To"] it remains read/write?

Also, I have converted this from VB.NET but I am fluent in both languages so if I have made any syntax errors it's from writing it free-hand. If that's the case, just let me know.

Thanks

0

1 Answer 1

1
+50

Create a Stub to use for the session as moq will have difficulty setting up the collection used to hold values in the indexed property. The other dependencies should work as expected with moq.

class HttpSessionStateMock : HttpSessionStateBase {
    private readonly IDictionary<string, object> objects = new Dictionary<string, object>();

    public HttpSessionStateMock(IDictionary<string, object> objects = null) {
        this.objects = objects ?? new Dictionary<string, object>();
    }

    public override object this[string name] {
        get { return (objects.ContainsKey(name)) ? objects[name] : null; }
        set { objects[name] = value; }
    }
}

Using the example method under test from your original question base on "RPI" being the clientType the Following Test was exercised to completion and passed as expected.

[TestMethod]
public async Task Index_ClientTypeIsRPI_ExpectCorrectRedirect() {
    //Arrange
    var mock = new MockRepository(MockBehavior.Loose) {
        DefaultValue = DefaultValue.Mock,
    };

    var session = new HttpSessionStateMock();//<-- session stub

    var controllerContext = mock.Create<ControllerContext>();
    controllerContext.Setup(_ => _.HttpContext.Session).Returns(session);

    var _controller = new MyController() {
        ControllerContext = controllerContext.Object
    };

    var transNo = "Asdf";
    var clientID = "123";
    var clientType = "RPI";
    var sessionKey = "REDIRECT_TO";
    var expected = "www.reddit.com";

    //Act
    await _controller.Index(transNo, true, clientID, clientType);
    var actual = _controller.HttpContext.Session[sessionKey].ToString();

    //Assert
    Assert.AreEqual(expected, actual);

}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.