Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Mock Session variables in ASP.net core unit testing project?

How to Mock Session variables in ASP.net core unit testing project?

1) I have created a mock object of a session.

Mock<HttpContext> mockHttpContext = new Mock<HttpContext>();
Mock<ITestSession> mockSession = new Mock<ISession>().As<ITestSession>();

2) Setup GetString() MEthod

mockSession.Setup(s => s.GetString("ModuleId")).Returns("1");

3) created controllerContext and assigned mockhttpContext object

controller.ControllerContext.HttpContext = mockHttpContext.Object; 

4) Trying to read from a controller.

HttpContext.Session.GetString("ModuleId")

Whereas I get a null value of "ModuleId". Please help me to mock session GetString() method

Example:

        //Arrange
        //Note: Mock session 
        Mock<HttpContext> mockHttpContext = new Mock<HttpContext>();
        Mock<ITestSession> mockSession = new Mock<ISession>().As<ITestSession>();
        //Cast list to IEnumerable
        IEnumerable<string> sessionKeys = new string[] { };
        //Convert to list.
        List<string> listSessionKeys = sessionKeys.ToList();
        listSessionKeys.Add("ModuleId");
        sessionKeys = listSessionKeys;
        mockSession.Setup(s => s.Keys).Returns(sessionKeys);
        mockSession.Setup(s => s.Id).Returns("89eca97a-872a-4ba2-06fe-ba715c3f32be");
        mockSession.Setup(s => s.IsAvailable).Returns(true);
        mockHttpContext.Setup(s => s.Session).Returns(mockSession.Object);
     mockSession.Setup(s => s.GetString("ModuleId")).Returns("1");         

        //Mock TempData
        var tempDataMock = new Mock<ITempDataDictionary>();
        //tempDataMock.Setup(s => s.Peek("ModuleId")).Returns("1");

        //Mock service
        Mock<ITempServices> mockITempServices= new Mock<ITempServices>();
        mockITempServices.Setup(m => m.PostWebApiData(url)).Returns(Task.FromResult(response));

        //Mock Management class method
        Mock<ITestManagement> mockITestManagement = new Mock<ITestManagement>();
        mockITestManagement .Setup(s => s.SetFollowUnfollow(url)).Returns(Task.FromResult(response));

        //Call Controller method
        TestController controller = new TestController (mockITestManagement .Object, appSettings);
        controller.ControllerContext.HttpContext = mockHttpContext.Object;            
        controller.TempData = tempDataMock.Object;

        //Act
        string response = await controller.Follow("true");

        // Assert
        Assert.NotNull(response);
        Assert.IsType<string>(response);
 
like image 908
Pankaj Dhote Avatar asked Dec 14 '22 00:12

Pankaj Dhote


2 Answers

First create class Named mockHttpSession and inherit from ISession.

public class MockHttpSession : ISession
{
    Dictionary<string, object> sessionStorage = new Dictionary<string, object>();

    public object this[string name]
    {
        get { return sessionStorage[name]; }
        set { sessionStorage[name] = value; }
    }

    string ISession.Id
    {
        get
        {
            throw new NotImplementedException();
        }
    }

    bool ISession.IsAvailable
    {
        get
        {
            throw new NotImplementedException();
        }
    }

    IEnumerable<string> ISession.Keys
    {
        get { return sessionStorage.Keys; }
    }

    void ISession.Clear()
    {
        sessionStorage.Clear();
    }

    Task ISession.CommitAsync()
    {
        throw new NotImplementedException();
    }

    Task ISession.LoadAsync()
    {
        throw new NotImplementedException();
    }

    void ISession.Remove(string key)
    {
        sessionStorage.Remove(key);
    }

    void ISession.Set(string key, byte[] value)
    {
        sessionStorage[key] = value;
    }

    bool ISession.TryGetValue(string key, out byte[] value)
    {
        if (sessionStorage[key] != null)
        {
            value = Encoding.ASCII.GetBytes(sessionStorage[key].ToString());
            return true;
        }
        else
        {
            value = null;
            return false;
        }
    }        
}

Then use this session in actual controller:

     Mock<HttpContext> mockHttpContext = new Mock<HttpContext>();
        MockHttpSession mockSession = new MockHttpSession();           
        mockSession["Key"] = Value;
        mockHttpContext.Setup(s => s.Session).Returns(mockSession);
        Controller controller=new Controller();
        controller.ControllerContext.HttpContext = mockHttpContext.Object;
like image 92
Pankaj Dhote Avatar answered May 13 '23 14:05

Pankaj Dhote


I used Pankaj Dhote's class for a mock ISession. I have to change one method from this:

bool ISession.TryGetValue(string key, out byte[] value)
{
    if (sessionStorage[key] != null)
    {
        value = Encoding.ASCII.GetBytes(sessionStorage[key].ToString());
        return true;
    }
    else
    {
        value = null;
        return false;
    }
}  

to the code below. Otherwise the reference to sessionStorage[key].ToString() returns the name of the type rather than the value in the dictionary.

    bool ISession.TryGetValue(string key, out byte[] value)
    {
        if (sessionStorage[key] != null)
        {
            value = (byte[])sessionStorage[key]; //Encoding.UTF8.GetBytes(sessionStorage[key].ToString())
            return true;
        }
        else
        {
            value = null;
            return false;
        }
    }
like image 30
L Nielsen Avatar answered May 13 '23 15:05

L Nielsen