Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/16.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
Asp.net mvc ASP/NET MVC:是否使用会话测试控制器?嘲笑?_Asp.net Mvc_Unit Testing_Mocking_Session - Fatal编程技术网

Asp.net mvc ASP/NET MVC:是否使用会话测试控制器?嘲笑?

Asp.net mvc ASP/NET MVC:是否使用会话测试控制器?嘲笑?,asp.net-mvc,unit-testing,mocking,session,Asp.net Mvc,Unit Testing,Mocking,Session,我在这里读了一些答案:测试视图和控制器,以及模拟,但我仍然不知道如何测试一个读取和设置会话值(或任何其他基于上下文的变量)的ASP.NET MVC控制器 如何为测试方法提供(会话)上下文?嘲笑就是答案吗?有人举过例子吗? 基本上,我想在调用controller方法并让controller使用该会话之前伪造一个会话。有什么想法吗?由于ASP.NET MVC框架使用抽象基类而不是接口,因此它不是非常友好的模拟(或者更确切地说,需要太多的设置才能正确模拟,并且在测试时会造成太多的摩擦,IMHO)。我们

我在这里读了一些答案:测试视图和控制器,以及模拟,但我仍然不知道如何测试一个读取和设置会话值(或任何其他基于上下文的变量)的ASP.NET MVC控制器 如何为测试方法提供(会话)上下文?嘲笑就是答案吗?有人举过例子吗?
基本上,我想在调用controller方法并让controller使用该会话之前伪造一个会话。有什么想法吗?

由于ASP.NET MVC框架使用抽象基类而不是接口,因此它不是非常友好的模拟(或者更确切地说,需要太多的设置才能正确模拟,并且在测试时会造成太多的摩擦,IMHO)。我们很幸运地为每个请求和基于会话的存储编写了抽象。我们使这些抽象非常简单,然后我们的控制器依赖于这些抽象来存储每个请求或每个会话

例如,下面是我们如何管理表单auth的内容。我们有一个ISecurityContext:

public interface ISecurityContext
{
    bool IsAuthenticated { get; }
    IIdentity CurrentIdentity { get; }
    IPrincipal CurrentUser { get; set; }
}
具体实现如下:

public class SecurityContext : ISecurityContext
{
    private readonly HttpContext _context;

    public SecurityContext()
    {
        _context = HttpContext.Current;
    }

    public bool IsAuthenticated
    {
        get { return _context.Request.IsAuthenticated; }
    }

    public IIdentity CurrentIdentity
    {
        get { return _context.User.Identity; }
    }

    public IPrincipal CurrentUser
    {
        get { return _context.User; }
        set { _context.User = value; }
    }
}

Scott Hanselman发表了一篇关于如何使用MVC实现quickapp的帖子,讨论了吸烟,并特别提到了“如何模仿不友好的事物。”

我发现模仿相当容易。下面是一个使用moq模拟httpContextbase(包含请求、会话和响应对象)的示例

[TestMethod]
        public void HowTo_CheckSession_With_TennisApp() {
            var request = new Mock<HttpRequestBase>();
            request.Expect(r => r.HttpMethod).Returns("GET");     

            var httpContext = new Mock<HttpContextBase>();
            var session = new Mock<HttpSessionStateBase>();

            httpContext.Expect(c => c.Request).Returns(request.Object);
            httpContext.Expect(c => c.Session).Returns(session.Object);

            session.Expect(c => c.Add("test", "something here"));            

            var playerController = new NewPlayerSignupController();
            memberController.ControllerContext = new ControllerContext(new RequestContext(httpContext.Object, new RouteData()), playerController);          

            session.VerifyAll(); // function is trying to add the desired item to the session in the constructor
            //TODO: Add Assertions   
        }
[TestMethod]
public void how_CheckSession_与_TennisApp(){
var request=newmock();
Expect(r=>r.HttpMethod).Returns(“GET”);
var httpContext=new Mock();
var session=newmock();
Expect(c=>c.Request).Returns(Request.Object);
Expect(c=>c.Session).Returns(Session.Object);
Expect(c=>c.Add(“test”,“此处某物”);
var playerController=NewPlayerSignupController();
memberController.ControllerContext=new ControllerContext(new RequestContext(httpContext.Object,new RoutedData()),playerController);
session.VerifyAll();//函数正在尝试将所需项添加到构造函数中的会话中
//TODO:添加断言
}

希望能有所帮助。

查看斯蒂芬·沃尔特关于伪造控制器上下文的帖子:


使用MVC RC 1,ControllerContext包装HttpContext并将其作为属性公开。这使得嘲弄变得容易多了。要使用Moq模拟会话变量,请执行以下操作:

var controller = new HomeController();
var context = MockRepository.GenerateStub<ControllerContext>();
context.Expect(x => x.HttpContext.Session["MyKey"]).Return("MyValue");
controller.ControllerContext = context;
var controller=new HomeController();
var context=MockRepository.GenerateStub();
Expect(x=>x.HttpContext.Session[“MyKey”]).Return(“MyValue”);
controller.ControllerContext=上下文;

有关更多详细信息,请参阅。

因为HttpContext是静态的,所以我使用Typemock隔离器对其进行模拟,Typemock还有一个为调用而定制的外接程序。

我使用了以下解决方案-制作一个我所有其他控制器都从中继承的控制器

public class TestableController : Controller
{

    public new HttpSessionStateBase Session
    {
        get
        {
            if (session == null)
            {
                session = base.Session ?? new CustomSession();
            }
            return session;
        }
    }
    private HttpSessionStateBase session;

    public class CustomSession : HttpSessionStateBase
    {

        private readonly Dictionary<string, object> dictionary; 

        public CustomSession()
        {
            dictionary = new Dictionary<string, object>();
        }

        public override object this[string name]
        {
            get
            {
                if (dictionary.ContainsKey(name))
                {
                    return dictionary[name];
                } else
                {
                    return null;
                }
            }
            set
            {
                if (!dictionary.ContainsKey(name))
                {
                    dictionary.Add(name, value);
                }
                else
                {
                    dictionary[name] = value;
                }
            }
        }

        //TODO: implement other methods here as needed to forefil the needs of the Session object. the above implementation was fine for my needs.

    }

}

哇,仅仅模仿一个方法就需要做很多工作:)这显然是“设置太多”的味道,这是使用抽象基类而不是接口作为依赖接缝的结果。当然,我见过一些项目,他们将设置代码放在“助手”类中,并反复使用。仅供参考,如果您的测试需要如此多的设置,以至于您需要一个“helper”类,那么您将面临痛苦和磨擦。我必须挖掘这个url,所以它是这样的:它可能不明显,但FakeControllerContext是一个自定义类。你可以在这里看到它的来源:上面的源链接似乎已经死了。。有人有副本吗?雅各布,你是人类中的英雄。只要您使用Controllerbase而不是Icontroller,代码仍然工作得很好
public class TestableController : Controller
{

    public new HttpSessionStateBase Session
    {
        get
        {
            if (session == null)
            {
                session = base.Session ?? new CustomSession();
            }
            return session;
        }
    }
    private HttpSessionStateBase session;

    public class CustomSession : HttpSessionStateBase
    {

        private readonly Dictionary<string, object> dictionary; 

        public CustomSession()
        {
            dictionary = new Dictionary<string, object>();
        }

        public override object this[string name]
        {
            get
            {
                if (dictionary.ContainsKey(name))
                {
                    return dictionary[name];
                } else
                {
                    return null;
                }
            }
            set
            {
                if (!dictionary.ContainsKey(name))
                {
                    dictionary.Add(name, value);
                }
                else
                {
                    dictionary[name] = value;
                }
            }
        }

        //TODO: implement other methods here as needed to forefil the needs of the Session object. the above implementation was fine for my needs.

    }

}
public class MyController : TestableController { }