Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/271.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为HttpContext.Current.Session编写单元测试时出现问题_C#_Asp.net Mvc_Unit Testing_Moq_Mstest - Fatal编程技术网

C# 为HttpContext.Current.Session编写单元测试时出现问题

C# 为HttpContext.Current.Session编写单元测试时出现问题,c#,asp.net-mvc,unit-testing,moq,mstest,C#,Asp.net Mvc,Unit Testing,Moq,Mstest,我有一个正在工作的应用程序,现在需要为它添加一整套单元测试。当前代码按如下方式存储用户信息: HttpContext.Current.Session["UserInfo"] = userData; 我正在使用moq进行测试,我的单元测试有以下代码: var server = new Mock<HttpServerUtilityBase>(MockBehavior.Loose); var response = new Mock<HttpResponseBase>(Mock

我有一个正在工作的应用程序,现在需要为它添加一整套单元测试。当前代码按如下方式存储用户信息:

HttpContext.Current.Session["UserInfo"] = userData;
我正在使用moq进行测试,我的单元测试有以下代码:

var server = new Mock<HttpServerUtilityBase>(MockBehavior.Loose);
var response = new Mock<HttpResponseBase>(MockBehavior.Strict);
var request = new Mock<HttpRequestBase>(MockBehavior.Strict);

var context = new Mock<HttpContextBase>();

context.SetupGet(x => x.Request).Returns(request.Object);
context.SetupGet(x => x.Response).Returns(response.Object);
context.SetupGet(x => x.Server).Returns(server.Object);

var controller = new LoginController();

controller.ControllerContext = new ControllerContext(
    context.Object, 
    new RouteData(), 
    controller);

JsonResult result = controller.LoginUser(
    new LoginHelper { 
        userName = "myusername", 
        password = "invalidpassword" 
        }
    ) as JsonResult;
var server=newmock(MockBehavior.Loose);
var响应=新模拟(MockBehavior.Strict);
var request=newmock(MockBehavior.Strict);
var context=newmock();
SetupGet(x=>x.Request).Returns(Request.Object);
SetupGet(x=>x.Response).Returns(Response.Object);
SetupGet(x=>x.Server).Returns(Server.Object);
var controller=新登录控制器();
controller.ControllerContext=新的ControllerContext(
上下文。对象,
新路由数据(),
控制器);
JsonResult=controller.LoginUser(
新登录密码{
userName=“myusername”,
password=“invalidpassword”
}
)因此,;
当然,当我到达登录进程尝试创建会话数据的位置时,我会得到一个“对象引用未设置为对象的实例”。错误是因为HttpContext.Current为null

一些研究表明,使用Current与MSTest不完全兼容,因此我理解可能需要更改存储/加载用户信息的方式。然而,我想要一些关于这条路的建议


如果您能就如何让我的单元测试正常工作提供任何建议,或者提供一种不同的方法来存储用户信息,使其与单元测试更加兼容,我将不胜感激。

这就是我提出的解决方案。这是我在不同地方发现的一些东西的组合,包括:

首先,我创建了两个类。。MockHttpSession和MockHelper

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

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

    public override void Abandon()
    {
        // Do nothing
    }
}

public class MockHelpers
{
    public static HttpContext FakeHttpContext()
    {
        var httpRequest = new HttpRequest("", "http://localhost/", "");
        var stringWriter = new StringWriter();
        var httpResponse = new HttpResponse(stringWriter);
        var httpContext = new HttpContext(httpRequest, httpResponse);

        var sessionContainer = new HttpSessionStateContainer(
            "id", 
            new SessionStateItemCollection(),
            new HttpStaticObjectsCollection(), 
            10, 
            true,
            HttpCookieMode.AutoDetect,
            SessionStateMode.InProc, 
            false);

        SessionStateUtility.AddHttpSessionStateToContext(httpContext, sessionContainer);

        return httpContext;
    }
}
公共类MockHttpSession:HttpSessionStateBase
{
Dictionary m_SessionStorage=新字典();
公共重写对象[字符串名称]
{
获取{return m_SessionStorage[name];}
set{m_SessionStorage[name]=value;}
}
公共覆盖无效放弃()
{
//无所事事
}
}
公共类模拟助手
{
公共静态HttpContext FakeHttpContext()
{
var httpRequest=新的httpRequest(“,”http://localhost/", "");
var stringWriter=新的stringWriter();
var httpResponse=新的httpResponse(stringWriter);
var httpContext=新的httpContext(httpRequest,httpResponse);
var sessionContainer=新的HttpSessionStateContainer(
“身份证”,
新建SessionStateItemCollection(),
新建HttpStaticObjectsCollection(),
10, 
是的,
HttpCookieMode.AutoDetect,
SessionStateMode.InProc,
假);
AddHttpSessionStateToContext(httpContext,sessionContainer);
返回httpContext;
}
}
然后,我更改了我的单元测试代码以使用这些代码:

var server = new Mock<HttpServerUtilityBase>(MockBehavior.Loose);
var response = new Mock<HttpResponseBase>(MockBehavior.Strict);
var request = new Mock<HttpRequestBase>(MockBehavior.Strict);
var session = new MockHttpSession();

var context = new Mock<HttpContextBase>();
context.SetupGet(x => x.Request).Returns(request.Object);
context.SetupGet(x => x.Response).Returns(response.Object);
context.SetupGet(x => x.Server).Returns(server.Object);
context.SetupGet(x => x.Session).Returns(session);

HttpContext.Current = MockHelpers.FakeHttpContext();

var controller = new LoginController();
controller.ControllerContext = new ControllerContext(context.Object, new RouteData(), controller);

JsonResult result = controller.LoginUser(new LoginHelper { userName = "MyUserName", password = ""InvalidPassword }) as JsonResult;
var server=newmock(MockBehavior.Loose);
var响应=新模拟(MockBehavior.Strict);
var request=newmock(MockBehavior.Strict);
var session=new MockHttpSession();
var context=newmock();
SetupGet(x=>x.Request).Returns(Request.Object);
SetupGet(x=>x.Response).Returns(Response.Object);
SetupGet(x=>x.Server).Returns(Server.Object);
SetupGet(x=>x.Session).Returns(Session);
HttpContext.Current=MockHelpers.FakeHttpContext();
var controller=新登录控制器();
controller.ControllerContext=新的ControllerContext(context.Object,new RouteData(),controller);
JsonResult=controller.LoginUser(新的LoginHelper{userName=“MyUserName”,password=”“InvalidPassword})作为JsonResult;
这能够成功地使用有效和无效密码测试代码


感谢大家的帮助

在ASP.Net MVC应用程序中使用
HttpContext.Current
很奇怪,但您可以简单地将
HttpContext.Current
设置为模拟上下文(创建这样的上下文完全是另一回事,所以:)。。。您真的应该考虑使用MVC方式访问上下文,或者将整个会话包装到接口中,并依赖于它,而不是直接访问
HttpContext.Current
@AlexeiLevenkov如果使用HttpContext.Current很奇怪,那么还有什么替代方法?提供良好的结果。另一种方法是将SessionStateBase注入控制器,而不是从HttpContext获取它。