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