ASP.NET MVC Mock / initialize sessionID

we have below code at service layer to get sessionID and go to external API for session correlation.

public static string GetCorrelationSession()
{
    if (HttpContext.Current != null && HttpContext.Current.Session != null)
    {
        //do some check and 
        if (!HttpContext.Current.User.Identity.IsAuthenticated | userContext == null)
                return HttpContext.Current.Session.SessionID;
    }
    else
    { 
        return null
    }
}

      

I tried and also googled how we can mock the httpcontext.current.session.sessionID but all examples seem to be asp.net controllers.

What's the best way to mock or initialize httpcontext.current.session.sessionID on a unit test?

+3


source to share


1 answer


Always avoid using a static method like you do because it's hard to mock. You need to give an abstract on how to get the session id. You can create an abstraction that will give the current session ID as shown below:

public interface ISessionProvider 
{
    string GetCorrelationSession();
}

      

then it has an implementation AspNetSessionProvider

that looks like this:

public interface AspNetSessionProvider : ISessionProvider
{
    public string GetCorrelationSession()
    {
        // Here you put how to get the current session Id.
    }
}

      

So how do you use it? You can use one of the following solutions:

Including dependencies:

If you are using dependency injection, inject ISessionProvider

into every controller or service where you need it through your contractor. Since it's not hard to mock an interface, all of your classes that use that interface can be tested very easily.



Ambient context with default implementation:

Use this solution only if ISessionProvider

you need so many services or controllers to access to become an end-to-end provider. This is similar to Injection (Injection Injection), but with a default implementation if not given. So, you create another new class, name it SessionProvider

so that its code looks like this:

public class SessionProvider
{
    private static readonly Lazy<ISessionProvider> InstanceProvider = new Lazy<ISessionProvider>(() => GetSessionProviderFromFactory() ?? new AspNetSessionProvider());

    private static Func<ISessionProvider> _factory;

    public static ISessionProvider Instance
    {
        get { return InstanceProvider.Value; }
    }

    public static void SetSessionProvider(Func<ISessionProvider> sessionProviderFactory)
    {
        if (_factory != null)
        {
            throw new InvalidOperationException("The session provider factory is already initialized");
        }
        if (sessionProviderFactory == null)
        {
            throw new InvalidOperationException("The session provider factory value can't be null");
        }

        _factory = sessionProviderFactory;
    }

    private static ISessionProvider GetSessionProviderFromFactory()
    {
        ISessionProvider sessionProvider = null;
        if (_factory != null)
        {
            sessionProvider = _factory();
            if (sessionProvider == null)
            {
                throw new InvalidOperationException("The session factory, when it is set, must not return a null isntance.");
            }
        }

        return sessionProvider;
    }
}

      

In your application code, you use it by calling this line whenever you need to access the session id:

SessionProvider.Instance.GetCorrelationSession();

      

In the test hardware setup of your unit tests, you can install the mocked instance using this code:

var mock = new Mock<ISessionProvider>(); 
// Setup the mock 
SessionProvider.SetSessionProvider(() => mock.Object);

      

+4


source







All Articles