ASP.NET MVC Mock /初始化sessionID

时间:2017-05-06 12:57:30

标签: asp.net asp.net-mvc unit-testing mocking

我们在服务层上面有一个代码来获取sessionID并传递给外部API进行会话关联。

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
    }
}

我试过并且也搜索了我们如何模拟httpcontext.current.session.sessionID,但所有示例似乎都是asp.net控制器。

在单元测试中模拟或初始化httpcontext.current.session.sessionID的最佳方法是什么?

1 个答案:

答案 0 :(得分:4)

始终避免像使用静态方法一样,因为很难模仿它们。您需要弄清楚如何获取会话ID。您可以创建一个抽象,给出当前会话ID,如下所示:

public interface ISessionProvider 
{
    string GetCorrelationSession();
}

然后有一个实现AspNetSessionProvider,如下所示:

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

那么如何使用呢?您可以使用以下解决方案之一:

依赖注入:

如果您正在使用依赖注入,则通过其控制器将ISessionProvider注入您需要的每个控制器或服务中。因为模拟界面并不困难,所以使用这个界面的所有类都可以很容易地测试。

具有默认实现的环境上下文:

仅当许多服务或控制器需要访问ISessionProvider时才使用此解决方案,因此它成为跨领域提供商。它类似于Property Injection(依赖注入),但如果没有设置则默认实现。因此,您创建另一个新类,我们将其命名为SessionProvider,因此其代码如下所示:

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;
    }
}

在您的应用程序代码中,只要您需要访问会话ID,就可以通过调用此行来使用它:

SessionProvider.Instance.GetCorrelationSession();

在单元测试的测试夹具设置中,您可以使用以下代码设置模拟实例:

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