2013-01-08 32 views
2

是否可以在不依賴「複製本地」的情況下運行單元測試,在運行時加載程序集?在運行時加載相關程序集時可以運行單元測試嗎?

更多細節:

我的.NET溶液看起來像這樣:

  • MainProject(EXE)[取決於 'Class1Project' 和使用 'AssemblyLoaderProject' 在運行時加載它。

    'Class1Project' 設置爲 '拷貝本地=假' 和 'AssemblyLoaderProject' 設置爲 '拷貝本地=真'

  • Class1Project(DLL)

  • AssemblyLoaderProject(負荷和解決依賴性在運行時組件使用AppDomain.CurrentDomain.AssemblyResolve和Assembly.LoadFrom)

  • UnitTestsProject(無論NUnit的或MSTest的)

在單元測試項目我試圖測試'Class1Project',我希望設置其配置與MainProject相同。

意思是說,UnitTestProject還用'copy local = false'引用'Class1Project',用'copy local = true'引用'AssemblyLoaderProject',並用它在運行時加載程序集。

但由於某些原因,單元測試無法執行,跑步者拋出FileNotFoundException,指出它無法解析'Class1Project'程序集。

試圖調試它,我發現測試運行器甚至沒有得到指示AssemblyLoaderProject加載程序集的代碼。

測試代碼如下所示:

[TestClass] 
public class UnitTest1 
{ 
    [TestMethod] 
    public void TestMethod1() 
    { 
     Loader.LoadAssemblies(); 
     Class1 cls = new Class1(); 
     Assert.IsTrue(true); 
    } 
} 

這是錯誤消息試圖用VS2012測試運行調試它的MSTest當我得到:

Test Name: TestMethod1 
Test FullName: UnitTestProject1.UnitTest1.TestMethod1 
Test Source: c:\Users\user\Documents\Visual Studio 2012\Projects\ClassLibrary1\UnitTestProject1\UnitTest1.cs : line 13 
Test Outcome: Failed 
Test Duration: 0:00:00.1177608 

Result Message: 
Test method UnitTestProject1.UnitTest1.TestMethod1 threw exception: 
System.IO.FileNotFoundException: Could not load file or assembly 'ClassLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.=== Pre-bind state information === 
LOG: User = \user 
LOG: DisplayName = ClassLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null 
(Fully-specified) 
LOG: Appbase = file:///C:/Users/user/Documents/Visual Studio 2012/Projects/ClassLibrary1/UnitTestProject1/bin/Debug 
LOG: Initial PrivatePath = NULL 
Calling assembly : UnitTestProject1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null. 
=== 
LOG: This bind starts in default load context. 
LOG: Using application configuration file: C:\PROGRAM FILES (X86)\MICROSOFT VISUAL STUDIO 11.0\COMMON7\IDE\COMMONEXTENSIONS\MICROSOFT\TESTWINDOW\vstest.executionengine.x86.exe.Config 
LOG: Using host configuration file: 
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config. 
LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind). 
LOG: Attempting download of new URL file:///C:/Users/user/Documents/Visual Studio 2012/Projects/ClassLibrary1/UnitTestProject1/bin/Debug/ClassLibrary1.DLL. 
LOG: Attempting download of new URL file:///C:/Users/user/Documents/Visual Studio 2012/Projects/ClassLibrary1/UnitTestProject1/bin/Debug/ClassLibrary1/ClassLibrary1.DLL. 
LOG: Attempting download of new URL file:///C:/Users/user/Documents/Visual Studio 2012/Projects/ClassLibrary1/UnitTestProject1/bin/Debug/ClassLibrary1.EXE. 
LOG: Attempting download of new URL file:///C:/Users/user/Documents/Visual Studio 2012/Projects/ClassLibrary1/UnitTestProject1/bin/Debug/ClassLibrary1/ClassLibrary1.EXE. 
Result StackTrace: at UnitTestProject1.UnitTest1.TestMethod1() 

回答

2

假設Loader.LoadAssemblies是註冊AssemblyResolve事件的方法,您收到此異常是因爲運行時無法通過探測找到ClassLibrary1.dll。理解爲什麼探索在這裏發揮作用是很重要的。探測被調用,因爲在通過Loader.LoadAssemblies加載任何程序集之前,該方法必須是Jitted。爲了正確地處理,運行時必須加載編譯時引用的類型的程序集。由於您已將「複製本地」設置爲false,因此文件ClassLibrary1.dll未被複制,也不在探測路徑中。因此,您的FileNotFoundException

首先,我會嘗試將Loader.LoadAssemblies轉換爲標有TestInitialize屬性的方法,以在每次測試之前運行。但是,根據在執行測試之前文件的複製位置,這可能也不起作用。您可能必須在測試設置中啓用部署並使用DeploymentItem屬性。

一個更大的問題是:如果你是單元測試,爲什麼你不能將'copy local'設置爲true來表示依賴關係,所以它們被複制到測試程序集中?

根據Loader.LoadAssemblies的具體情況,您可能會遇到由程序集加載到多個或不同的加載上下文所導致的其他問題。這可能導致像InvalidCastException這樣的問題,其中錯誤表示您不能將類型'X'轉換爲鍵入'X'。但是,您可能是安全的,因爲如果未通過探測找到AppDomain.AssemblyResolve,則會將程序集加載到Load上下文中。

+0

在這種情況下,在TestInitialize方法中調用'Loader.LoadAssemblies'。加載器使用完整路徑加載class1project,所以我不需要使用複製本地或啓用部署。你可以解決我的測試項目中包含從Class1派生的類(駐留在Class1Project中)的情況嗎?在這種情況下,當我嘗試在測試運行器中加載程序集時會發生jit和探測階段,並且失敗。 – avivr

+0

如果我在我的主要.exe程序集中做同樣的事情,創建一個派生自Class1的類,應用程序將運行得很好。它是否嘗試僅在第一次訪問派生類(在Lodaer運行後發生)時纔對JIT派生類進行JIT操作,並且在測試環境中,當文件加載時,測試運行器會嘗試JIT所有程序集的類型?也許是爲了解析哪一個包含測試? – avivr

+0

@avivr我相信你完全正確。測試框架正在加載測試項目中的所有類型,尋找測試。這發生在'TestInitialize'之前,因此'LoadAssemblies'在探測發生之前沒有運行並且拋出相同的異常。 –

0

你不得不做出這樣的DLL'Class1Project'可用於加載器,因此,如果您不想將項目設置爲始終複製它,則可以使用屬性將其複製以進行測試,以便負載可以找到它。

+0

加載器使用Assembly.LoadFrom(FULL_PATH_TO_Class1ProjectDll),所以它應該可以在任何地方使用而不需要複製文件。 – avivr

0

There is a bug in VS2012 test runner.在我的項目中,我將所有依賴關係設置爲copy local = true,並且仍有一些dll不會被複制到「Out」文件夾,從而導致測試失敗。如果我在VS2010下運行相同的測試,一切都運行完美。

使用DeploymentAttribute確實有幫助,但它不應該是必需的。

相關問題