0

我使用Visual Studio 2010的内置测试工具和此article中的类库来测试帐户/ Loggon操作以创建假控制器上下文。 当我运行的测试方法,这行代码:测试帐户/登录操作

FormsAuthentication.SetAuthCookie(username, false);  

抛出异常:对象引用未设置到对象

为了测试loggon行动的一个实例,我想我应该创建带有假控制器上下文的控制器,该控制器上下文具有Cookie集合。这里是我的测试代码块:

AccountController controller = new AccountController(); 
    var cookies = new HttpCookieCollection(); 

    controller.ControllerContext = new FakeControllerContext(controller, cookies); 

    ActionResult result = controller.RemoteLogOn(username, password); 

回答

9

我不知道这是否是正确的方式,但是这是我们做什么,和它的作品。

不是直接使用FormsAuthentication.SetAuthCookie,而是将其抽象为接口,例如IFormsAuthenticationService,并按照常规实现。

接受,在你的MVC控制器在需要时e.g:

public AccountController(IFormsAuthenticationService formsAuthenticationService) 
{ 
    _formsAuthenticationService = formsAuthenticationService; // should use DI here 
} 

public ActionResult LogOn(string username, string pw) 
{ 
    if (yourLogicWhichChecksPw) 
     _formsAuthenticationService.SetAuthCookie(username, false); 
    return RedirectToAction("Index"); 
} 
在单元测试

然后,使用类似Moq伪造出接口。

var username = "blah"; 
var pw = "blah"; 
var fakesFormsAuth = new Mock<IFormsAuthenticationService>(); 
fakeFormsAuth.Verify(x => x.SetAuthCookie(username, false), Times.AtLeastOnce());     
var controller = new AccountController(fakedFormsAuth.Object); 
controller.LogOn(username, pw); 

原因的嘲讽,这是因为完全没有必要单元测试表单验证。它是ASP.NET框架的一个内置,经过充分测试和稳定的部分。这就是为什么我们嘲笑那些我们不关心底层实现的东西,而是我们只测试满足某些条件(它被称为,抛出异常,设置了一些变量等等)。

测试你自己的代码,而不是.NET的机制。

至于Stephen Walther的文章,这更多的是在您的测试需要某些代码测试需要请求中的数据时伪造RequestContext。如User.Identity,Request.IsAuthenticated,表单变量,等等。这就是你需要假冒的背景下,如下面的代码:

public ActionResult Save(SomeModel) 
{ 
    var user = Request.User.Identity; // this will be null, unless you fake the context. 
} 
+2

这是我来的东西其实我可以最接近自从我开始寻找如何模拟SetAuthCookie之后就明白了。谢谢你。 – dartacus 2012-08-02 13:17:09