我認爲你是相當正確的軌道上,因爲你從你的單元測試抽象掉數據庫通信和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。如果可能,我同意使用'IPrinciple'接口。這是.NET的核心概念,可以在整個應用程序中使用,而不會有任何問題。 – Steven 2011-03-10 09:08:14
我已經考慮過使用模型綁定器並將它傳遞給方法,但由於每一次調用(除了我的通用內容控制器中的那些)都需要身份,我覺得它違反了DRY,並認爲更好的解決方案是擁有它通過控制器級別傳入。 – 2011-03-10 15:29:31