1

請溫柔,我對於新手,這個IOC/MVC的事情,但我想。我瞭解DI用於測試目的的價值以及IoC在運行時如何解決依賴關係,並且已經通過了幾個適用於您的標準CRUD操作的示例...ASP.NET MVC和IOC - 鏈注入

我開始一個新項目並且無法上來用乾淨的方式來完成用戶權限。我的網站主要是通過任何帶有功能的頁面(註冊,常見問題,關於我們等)進行登錄。我有一個自定義的身份,有幾個額外的屬性,控制訪問數據...所以... ...

使用Ninject,我已經綁定具體類型*的方法(Bind<MyIdentity>().ToMethod(c => MyIdentity.GetIdentity());,這樣,當我添加MyIdentity一個構造函數,它是基於方法調用的結果注入的。

這一切工作正常。是否適合(從GetIdentity()方法)直接查詢請求cookies對象(通過FormsAuthentication)?在測試控制器時,我可以通過在一個身份,但GetIdentity()方法將基本上不可測...

此外,在的getIdentity()米方法,我會查詢數據庫。我應該手動創建一個存儲庫的具體實例嗎?

還是有更好的辦法一起?

回答

4

我認爲你是相當正確的軌道上,因爲你從你的單元測試抽象掉數據庫通信和ASP.NET的依賴。不要擔心你無法在測試中測試所有的東西。在您的應用程序中始終存在不可測試的代碼行。 GetIdentity就是一個很好的例子。在您的應用程序的某處,您需要與特定於框架的API進行通信,並且您的單元測試無法涵蓋此代碼。

可能仍有改進的餘地,但。雖然未經測試的GetIdentity不是問題,但它實際上可由應用程序調用。它只是掛在那裏,等着有人不小心打電話給它。那麼爲什麼不抽象身份的創造。例如,創建一個知道如何爲當前上下文獲取正確標識的抽象工廠。你可以注入這個工廠,而不是注入身份本身。這使您可以在應用程序的組合根目錄附近定義一個實現,並且可以在應用程序的其餘部分之外進行定義。除此之外,代碼更清楚地傳達了正在發生的事情。沒有人需要問「我實際上得到了哪個身份?」,因爲他們所稱的工廠的方法很明顯。

下面是一個例子:

public interface IIdentityProvider 
{ 
    // Bit verbose, but veeeery clear, 
    // but pick another name if you like, 
    MyIdentity GetIdentityForCurrentUser(); 
} 

在你的作文根,你可以有一個這樣的實現:

private sealed class AspNetIdentityProvider : IIdentityProvider 
{ 
    public MyIdentity GetIdentityForCurrentUser() 
    { 
     // here the code of the MyIdentity.GetIdentity() method. 
    } 
} 

作爲招有時我有我的測試對象,對工廠和產品兩個,只是爲了方便在單元測試。例如:

private sealed class FakeMyIdentity 
    : FakeMyIdentity, IIdentityProvider 
{ 
    public MyIdentity GetIdentityForCurrentUser() 
    { 
     // just returning itself. 
     return this; 
    } 
} 

這樣你可以注入一個FakeMyIdentity在期望一個IIdentityProvider構造。我發現這不會犧牲測試的可讀性(這很重要)。 當然你會希望有儘可能少的代碼儘可能在AspNetIdentityProvider,因爲你不能測試它(自動)。同時確保你的類不依賴任何框架特定的部分。如果是這樣,你也需要抽象。

我希望這是有道理的。

1

有兩件事情我還挺有什麼不同......在這裏

  1. 我會使用一個自定義的IPrincipal與所有身份驗證需求所需對象的屬性。然後,我會將它與自定義Cookie創建和AuthenticateRequest事件結合使用,以避免每次請求都會調用數據庫。

  2. 如果我的IPrincipal/Identity在另一個類中需要,我會將它作爲方法參數傳遞,而不是將它作爲它自己的類的依賴項。
    當沿着這條路線走時,我使用自定義模型粘合劑,這樣他們就成爲我的行爲的參數,而不是奇蹟般地出現在我的動作方法中。
    注意:這只是我一直在做的事情,所以拿一粒鹽。

對不起,這可能會拋出更多的問題比答案。隨意提出更多關於我的方法的問題。

+0

+1。如果可能,我同意使用'IPrinciple'接口。這是.NET的核心概念,可以在整個應用程序中使用,而不會有任何問題。 – Steven 2011-03-10 09:08:14

+0

我已經考慮過使用模型綁定器並將它傳遞給方法,但由於每一次調用(除了我的通用內容控制器中的那些)都需要身份,我覺得它違反了DRY,並認爲更好的解決方案是擁有它通過控制器級別傳入。 – 2011-03-10 15:29:31