C# 单元测试简单成员资格提供者?

C# 单元测试简单成员资格提供者?,c#,asp.net-mvc,unit-testing,asp.net-mvc-4,tdd,C#,Asp.net Mvc,Unit Testing,Asp.net Mvc 4,Tdd,如何对使用简单成员资格提供程序的控制器进行单元测试 控制器将MyViewModel对象作为输入并将其插入数据库。当操作成功完成时,用户被重定向到仪表板 控制器将Web安全性作为依赖项。所以当进行单元测试时,我得到HttpContext的参数null异常,如下所示 userLakshya.UserId=WebSecurity.HasUserId? WebSecurity.CurrentUserId : -1; 如何将HttpContext参数传递给控制器? 代码列表: [HttpPost]

如何对使用简单成员资格提供程序的控制器进行单元测试

控制器将MyViewModel对象作为输入并将其插入数据库。当操作成功完成时,用户被重定向到仪表板

控制器将Web安全性作为依赖项。所以当进行单元测试时,我得到HttpContext的参数null异常,如下所示

userLakshya.UserId=WebSecurity.HasUserId? WebSecurity.CurrentUserId : -1;

如何将HttpContext参数传递给控制器?

代码列表:

    [HttpPost]
    public ActionResult Create(MyViewModel myVM)
    {
        MyModel myModel = myVM.Model;
        if (ModelState.IsValid)
        {
            userLakshya.UserId = WebSecurity.HasUserId ? WebSecurity.CurrentUserId : -1;
            db.MyModels.Add(myModel);
            db.SaveChanges();
            return RedirectToAction("Dashboard");
        }
        return View(myVM);
    }

    [TestMethod]
    public void TestLoginAndRedirectionToDashboard()
    {
        MyController cntlr = new MyController();
        var ret = ulCntlr.Create(new MyViewModel(){
            //Initialize few properties to test
        });
        /*
         * Controller throws parameter null exception for HttpContext
         * => Issue: Should I pass this? since the controller uses WebSecurity inside
         * */
        ViewResult vResult = ret as ViewResult;
        if (vResult != null)
        {
            Assert.IsInstanceOfType(vResult.Model, typeof(UserLakshya));
            UserLakshya model = vResult.Model as UserLakshya;

            if (model != null)
            {
                //Assert few properties from the return type.
            }
        }
    }  

您的问题是您的Create方法违反了标准,即您的方法应该“依赖于抽象,而不依赖于具体”

你应该重构你的代码,这样你就不用直接使用WebSecurity类,而是使用一个抽象,比如你可以创建一个ISecurity接口。您的具体版本的ISecurity(例如Security)可以包含对WebSecurity的引用,从而删除直接依赖关系

(您已经为数据库依赖项(即db成员)执行了此操作,您只需要为代码的安全性执行此操作。)

e、 g

而不是:

userLakshya.UserId = WebSecurity.HasUserId ? WebSecurity.CurrentUserId : -1;
您可以使用:

userLakshya.UserId = security.GetUserId();
然后,为了测试“Create”控制器,您可以使用模拟框架(例如)模拟ISecurity的行为(实际上,我还建议您模拟“db”对象的行为)。使用Moq代码进行模拟的示例如下:

var mock = new Mock<ISecurity>();
mock.Setup(security=> security.GetUserId()).Returns("ATestUser");
var mock=new mock();
mock.Setup(security=>security.GetUserId()).Returns(“ATestUser”);

您遇到的问题是,您的Create方法违反了标准,即您的方法应该“依赖于抽象。不要依赖于具体”

你应该重构你的代码,这样你就不用直接使用WebSecurity类,而是使用一个抽象,比如你可以创建一个ISecurity接口。您的具体版本的ISecurity(例如Security)可以包含对WebSecurity的引用,从而删除直接依赖关系

(您已经为数据库依赖项(即db成员)执行了此操作,您只需要为代码的安全性执行此操作。)

e、 g

而不是:

userLakshya.UserId = WebSecurity.HasUserId ? WebSecurity.CurrentUserId : -1;
您可以使用:

userLakshya.UserId = security.GetUserId();
然后,为了测试“Create”控制器,您可以使用模拟框架(例如)模拟ISecurity的行为(实际上,我还建议您模拟“db”对象的行为)。使用Moq代码进行模拟的示例如下:

var mock = new Mock<ISecurity>();
mock.Setup(security=> security.GetUserId()).Returns("ATestUser");
var mock=new mock();
mock.Setup(security=>security.GetUserId()).Returns(“ATestUser”);

1
WebSecurity
不实现任何接口(它是静态类)2。在我的代码中,
Create
是从客户端调用的操作方法。传递附加参数,如
WebSecurity
ISecurity
是否可行,比如我使用默认构造函数实例化自定义类,以保存
WebSecurity.HasUserId
WebSecurity.CurrentUserId
。我对操作应用
Authorize
filter属性。我认为构造函数应该在
授权之前首先被调用。在这种情况下,
WebSecurity
将为空。我说的对吗?@MikeCole Yes Moq使用Mock来实例化一个Mock对象。参见第二个示例。当他们把这个框架命名为“Moq”时,我也会认为他们会用“Moq”来代替
WebSecurity
不实现任何接口(它是静态类)2。在我的代码中,
Create
是从客户端调用的操作方法。传递附加参数,如
WebSecurity
ISecurity
是否可行,比如我使用默认构造函数实例化自定义类,以保存
WebSecurity.HasUserId
WebSecurity.CurrentUserId
。我对操作应用
Authorize
filter属性。我认为构造函数应该在
授权之前首先被调用。在这种情况下,
WebSecurity
将为空。我说的对吗?@MikeCole Yes Moq使用Mock来实例化一个Mock对象。参见第二个示例。当他们把这个框架命名为“Moq”时,我也会认为他们会用“Moq”来代替。