1

首先,我對此問題的開放性質表示歉意。然而,我已經癱瘓了好幾個月,儘管同意搜索,仍然無法克服這一點。構建可測試的MVC3和EF 4.1應用程序

我一直在研究MVC/EF應用程序一段時間。我想了解如何設計和構建由Entity Framework(4.1)支持的可測試MVC3應用程序。您可以在hereherehere這個主題上看到幾個問題。

我不想讓它複雜化,但我希望它是一個可以增長的聲音,鬆散耦合的設計。就我的理解,下面是非常最低限度所需的組件:

MVC應用程序
這是非常薄。儘可能少的邏輯在這裏。我的觀點具有儘可能少的條件邏輯,我的觀點模型不過是POCO,而我的控制器只是簡單地處理視圖模型和領域模型之間的映射,並呼叫服務。

服務層+接口(單獨的程序集)
這是我所有的業務邏輯去的地方。這樣做的目標是能夠掌控任何瘦客戶端(表單應用程序,移動應用程序,Web服務),以暴露我的應用程序的內心。服務層的接口位於另一個程序集中。

核心工具/交叉+接口(單獨的組件)
這是東西,我建立這不是具體到我的應用程序,而不是框架或我使用任何第三方插件的一部分。再次,這些組件的接口位於它們自己的組件中。

存儲庫(EF上下文)
這是我的域模型和我的數據庫之間的接口。我的服務層使用它來通過域模型檢索/修改我的數據庫。

域模型(EF POCOs)
EF4生成的POCOs。其中的一些可以被擴展爲方便起見,以其它嵌套屬性或計算的特性(如Order.Total = Order.Details.Sum(d => d.Price)

IoC容器
這就是用於注射我的混凝土/假依賴(服務/實用程序)到MVC應用程序&服務。構造函數注入只用於整個。

這裏就是我掙扎:

1)集成測試是適當的對單元測試。例如,一些程序集是否需要混合兩者,或者是主要針對MVC應用程序的集成測試以及我的服務&實用程序的單元測試?

2)難道我打擾寫存儲庫/域模型代碼的測試嗎?當然就POCO而言,這不適用。但是,當我延長我的POCO和計算屬性時呢?

3)用於存儲庫的正確模式。我知道這是非常主觀的,因爲每次我看到這個討論時,似乎每個人都有不同的方法。因此,很難確定要走哪條路。例如,我是否會推出自己的存儲庫,或者直接使用EF(DbContext)?

4)當我爲我的服務編寫測試時,是模擬我的存儲庫還是使用SQL Lite構建模擬數據庫並對其進行測試? (見辯論herehere)。

5)這是一件全有或無關的事情,如果我做任何測試,我應該測試一切?或者,是否任何測試都比沒有測試更好?如果是後者,哪裏是最重要的領域(我在考慮服務層)?

6)是否有任何好的書籍,文章或示例應用程序可以幫助我解答大部分這些問題?

我認爲這就夠了。如果結果太開放了,讓我知道,我很樂意關閉。但是,再次,我已經花了數月的時間試圖獨自一人解決這個問題,但沒有運氣。

回答

5

這是一個非常複雜的問題。您的每一點都足以成爲一個單獨的問題,因此我只寫簡短的摘要:

  1. 集成測試和單元測試不會相互替代。如果您想要經過良好測試的應用程序,您總是需要兩者。單元測試是單獨測試邏輯(通常藉助於模擬,存根,假貨等),而集成測試則用於測試組件是否正確地一起工作(=無嘲笑,存根或假貨)。何時使用集成測試以及何時使用單元測試確實取決於您正在測試的代碼和您所遵循的開發方法(例如TDD)。

  2. 如果您的POCO包含任何邏輯,您應該爲它們編寫單元測試。存儲庫中的邏輯通常嚴重依賴於數據庫,因此模擬上下文並在沒有數據庫的情況下測試它們通常是無用的,因此您應該使用集成測試來覆蓋它們。

  3. 這實際上取決於您對存儲庫的期望。如果它只是愚蠢的DbContext/DbSet包裝器,那麼庫的值就是零,它很可能不會使你的代碼單元在一些引用的討論中描述的可測試。如果它包裝查詢(上層沒有LINQ-to-entites),暴露對聚合根的訪問,那麼知識庫的含義就是正確分離數據訪問和暴露可模擬接口。

  4. 它完全依賴於以前的觀點。如果您公開IQueryable或接受Expression<Func<>>的方法在內部傳遞給IQueryableyou cannot correctly mock the repository(您可以,但您仍然需要將每個單元測試與測試相同邏輯的集成測試進行配對)。 LINQ到實體是「副作用」/泄漏抽象。如果你完全包裝倉庫中的查詢並使用你自己的聲明性查詢語言(規範模式),你可以嘲笑它們。

  5. 任何測試都比不測試更好。許多方法學期望高密度覆蓋。 TDD甚至達到100%的測試覆蓋率,因爲測試總是先寫入,沒有測試就沒有邏輯。這是關於您所遵循的方法,以及如果您需要針對代碼段進行測試,您可以選擇專業決策。

  6. 我不認爲有任何「讀這個,你會知道如何做到這一點」。這是軟件工程和軟件工程是一門藝術。在任何情況下都沒有藍圖(在大多數情況下都不適用)。

+0

謝謝,拉迪斯拉夫。我知道這不是一個容易回答的問題,並且我感謝你無論如何都在刺探它。爲了澄清,我可能會有一些愚蠢的存儲庫,並將LINQ-to-entities邏輯保留在我的服務層中。所以它真的會在我的服務層中承擔很多責任(業務+查詢邏輯)。這是否會導致它自己的問題 - 即對此進行權衡與爲我的LINQ-to-entities邏輯創建存儲庫並使我的服務層嚴格遵守業務邏輯有什麼關係?再次,我知道這是主觀的,我只是想確保我理解這種權衡。 –

+0

_作爲一個離題的方面說明,我想感謝你對SO社區的貢獻,尤其是我的問題,因爲你經常會回答我的很多問題,其中大部分似乎都需要很多時間和你的想法。它不會被忽視._ –

相關問題