2014-03-28 51 views
6

我在我的解決方案中有5個程序集:AB,B.Test,CC.TestBC都參考A(並不相互引用)。 B.Test參考文獻AB,C.Test參考文獻ACDeploymentItem打破單獨程序集中的EntityFramework單元測試

B.Test,我建立在B定義的EntityFramework6 DbContext對象:

[TestMethod] 
public void TestB() { 
    MyBContext c = new MyBContext(); 
} 

C.Test,我有一個空的單元測試用DeploymentItem

[TestMethod] 
[DeploymentItem("data.txt")] 
public void TestC() { } 

當我運行兩個單獨測試,他們都通過。然而,當我的相同測試運行的一部分「運行所有」兩個測試在一起,TestB失敗,出現以下異常:

「的實體框架提供型「System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer'註冊在ADO.NET提供程序的應用程序配置文件中,該提供程序的名稱爲'System.Data.SqlClient',因此無法加載。請確保使用程序集限定名,並且程序集可用於運行請參閱http://go.microsoft.com/fwlink/?LinkId=260882瞭解更多信息。「

當我改變TestC註釋掉DeploymentItem屬性如下:

[TestMethod] 
//[DeploymentItem("data.txt")] 
public void TestC() { } 

兩個測試現在通過。 TestB創建上下文而不引發異常。不知何故,在DeploymentItemAttribute中加入程序集C.Test正在打破一個測試,它在一個單獨的程序集中不使用DeploymentItemB.Test(並且我在使用DeploymentItem的C.Test中進行了其他測試,因此刪除此一個實例不會從該庫中刪除引用) 。這讓我花了很多時間甚至縮小了失敗的範圍,而且我完全不知道下一步該怎麼做才能解決這個問題。

編輯:我發現了一些關於MSDN似乎解決這個問題的信息(儘管我不明白爲什麼)。

  1. 通過Resharper測試運行器或其他測試運行器運行單元測試似乎可以解決問題。只有當我通過VisualStudio的(2012,如果它的事項)運行單元測試做測試失敗
  2. 添加以下代碼到我的組件,其定義的DbContext似乎解決該問題:

    static MyDbContext() { 
        var _ = typeof(System.Data.Entity.SqlServer.SqlProviderServices); 
    } 
    

    (該MSDN上的答案建議將其添加到上下文類本身,我將它添加到該上下文的Factory類型,而不是具有相同的有益結果)。

所以它看起來像我們有一個答案「我如何使我的單元測試工作?」但不是「爲什麼這首先發生?」這個問題。考慮到這個解決方案,我懷疑EF6在動態加載類型和程序集方面有些快速和鬆動,並且某些程序集在從某些類型的地方執行測試時未被加載。

回答

1

其原因來自EF及其提供商之間的鬆散耦合以及MSTest運行測試的方式。

關於提供者,實體框架可以與各種不同的提供者一起工作。 SQL Server提供者僅僅是一個例子。 EntityFramework.dll對SQL Server提供程序程序集沒有硬性依賴性,因爲在將EF與任何其他提供程序一起使用時不需要它。

這意味着使用EF時應確定使用哪個提供程序並確保提供程序集與應用程序或測試一起部署。這通常通過將提供程序NuGet包安裝到應用程序或測試項目中來完成。如果NuGet包安裝到應用程序/測試項目中,則提供程序集將被放入bin文件夾,而不管它是否直接在代碼中引用。如果供應商的NuGet軟件包僅安裝到解決方案中的其他項目(例如類庫)中,而不是直接安裝到應用程序/測試項目中,則情況並非如此。

由於歷史原因,SQL Server提供程序在主實體框架NuGet包中提供,因此對於SQL Server提供程序,它是需要在應用程序/測試項目中安裝的EntityFramework包。如果您不希望將提供程序/ EntityFramework軟件包安裝到應用程序/測試項目中,則可以設置其他邏輯以確保部署該程序集。

現在MSTest變得更加棘手,因爲它有自己的部署規則和配置。這意味着僅僅安裝NuGet包可能還不夠,您可能需要設置特定的MSTest部署規則以確保正確複製程序集。另一個解決方案是不使用MSTest。在幾年前我們從MSTest切換到xUnit的EF團隊中,這樣做的問題少得多。

8

問題是由於編譯器不輸出EntityFramework.SqlServer.dll,因爲它不檢測它是否在某處使用(它只能通過依賴注入來使用)。最簡單的解決方案是在測試中使用其中一種裝配類型。

例如你可以創建一個屬性或方法(你不需要使用它,只需公開它就足夠了)。爲了解決這個問題,我在一個測試助手裏面創建了一個屬性:

public static System.Data.Entity.SqlServer.SqlProviderServices EnsureAssemblySqlServerIsCopied { get; set; } 
相關問題