聽起來像你是在我幾年前的狀態。
請注意,如果您需要更多幫助,我會向您發送一些代碼。很難把所有的代碼放在這裏。
我試着解釋我正在開發的項目中的當前體系結構。這篇文章有點冗長,但我想給你一個關於如何使用IOC在很多方面可以幫助你的大局。
所以我使用Ninject。在嘗試使用Castle Windsor一段時間後,我發現Ninject易於啓動和運行。 Ninject有一個很酷的網站,可以幫助你入門。
我所有的項目結構首先如下:(自上而下和它的MVC)
查看 - 剃刀 視圖模型 - 我用按次1個視圖模型
ViewModelBuilder - 爲我的視圖構建我的視圖模型(用於將代碼從我的控制器中抽離出來,以便控制器保持整潔)
AutoMapper - 域實體映射到我的視圖模型
控制器 - 叫我的服務層來獲得域實體
域實體 - 我的域名
ServiceLayer(業務交涉層) - 調用我的存儲庫層以獲取域實體或這些的集合
AutoMapper再次 - 從我的第三方供應商映射自定義類型轉換成我的域實體
RepositoryLayer - 確實CRUD操作我的數據存儲
這是一個層次,但類型的域實體沿側坐並用於幾個不同的層。
注:在這篇文章中提到的一些額外的工具有:
AutoMapper - 地圖實體到其他實體 - 無需編寫映射代碼
起訂量負載 - 允許你嘲笑單元測試的東西。這在後面會提到。
現在,關於Ninject。
每層都標有接口。必須這樣做,Ninject才能對自己說。
當我發現IVehicleRepository注入一個真正的VehicleRepository,甚至注入它與FakeVehicleRepository,如果我需要一個假的。
(這涉及到你的評論 - 「這將讓我的一切綁定到一個測試XML庫」)
現在,每一層都有contstructor使Ninject(或任何其它的IOC容器)可以注入需要的東西:
public VehicleManager(IVehicleRepository vehicleRepository)
{
this._vehicleRepository = vehicleRepository;
}
VehicleManager位於我的serviceLayer中(不要與任何與Web服務相關的混淆)。服務層實際上就是我們所說的業務層。似乎很多人都在使用文字服務。 (儘管我認爲這很煩人,因爲它讓我想到Web服務或WCF,而不僅僅是一個業務層......無論如何......)
現在沒有進入Ninject的基本設置下面的行在我的NinjectWebCommon.cs代碼告訴ninject做什麼:
kernel.Bind<IVehicleRepository>().To<VehicleRepository>().InRequestScope();
這是說:
嘿ninject,當我問IVehicleRepository給我一個具體的實施VehicleRepository的。
如前所述,我可以將VehicleRepository替換爲FakeVehicleRepository,這樣我就不必從真實數據庫中讀取數據。
因此,正如你現在可以想象的那樣,每一層只依賴於接口。
我不知道你做了多少單元測試,但你也可以想象,如果你想單元測試你的服務層,並且它具有對你的存儲庫層的具體引用,那麼你將無法像你一樣進行單元測試實際上打你的存儲庫,因此從一個真正的數據庫中讀取。
記住單元測試稱爲單元測試,因爲它只測試一件事情。因此單詞UNIT。所以,因爲每個人都只知道接口,這意味着你可以在你的服務層上測試一個方法並模擬庫。
所以,如果你的服務層具有這樣的方法:
public bool ThisIsACar(int id)
{
bool isCar = false;
var vehicle = vehicleRepository.GetVehicleById(id);
if(vehicle.Type == VehicleType.Car)
{
isCar = true;
}
else
{
isCar = false;
}
}
你不會希望vehicleRepository要打電話,所以你可以起訂量是什麼VehicleRepository給你。如果它實現了一個接口,你大多隻能使用Mock的東西。
So your unit test would look like this (some pseudo code here):
[TestMethod]
public void ServiceMethodThisIsACar_Returns_True_When_VehicleIsACar()
{
// Arrange
_mockRepository.Setup(x => x.ThisIsACar(It.IsAny<int>)).returns(new Car with a type of VehicleType.Car)
// Act
var vehicleManager = new VehicleManager(_mockVehicleRepository.Object);
var vehicle = vehicleManager.ThisIsACar(3);
// Assert
Assert.IsTrue(vehicle.VehicleType == VehicleType.Car)
}
因此,大家可以看到,在這一點上,這是非常簡單的,你只想要測試的IF語句在服務層,以確保結果是正確的。
你會在自己的單元測試中測試你的倉庫,如果你正在使用它,可能會模擬實體框架的工作。
所以,總的來說,我會說,使用任何IOC容器都能讓你以最少的痛苦快速運行。
我也會說,嘗試和單元測試一切,你可以。這有很多不同的原因。很明顯,它會測試你編寫的代碼,但它也會立即告訴你,如果你做了一些愚蠢的事情,比如新建一個具體的存儲庫。你會很快看到你不會有一個接口來模擬你的單元測試,這將導致你回去重構你的代碼。
我發現使用IOC,需要一段時間才能得到它。它把你的垃圾混淆直到有一天它只是點擊。在那之後,你很容易想到你如何在沒有它的情況下生活。
這裏的東西我不能生活在沒有 Automapper 起訂量 流利驗證 ReSharper的清單 - 有些恨它,我喜歡它,主要是它的單元測試UI。
無論如何,這是太長了。讓我知道你的想法。
感謝 拉斯
我只是刪除一切,並試圖再次統一,因爲這是我來最接近的一次。在預感上,我刪除了一個構造函數,它帶有參數,我認爲它工作。我不知道爲什麼當空的構造函數可用時它鎖定在構造函數上(我所做的只是評論其他)。明天早上將繼續關注此事。 – 2013-02-12 21:48:29