2016-05-20 60 views
3

說明當多個單元測試複製相同的文件,運行所有的單元測試失敗

我寫單元測試的方法,該副本從源文件到目的地。基本上,它包括這樣的代碼:

public void MyMethod() 
{ 
    // ... 
    File.Copy(source, destination, true); 
    // ... 
} 

以我單元測試項目,我有一個測試文件:(test.png),它位於在我的單元測試項目的Resources文件夾。我已將Copy to Output屬性設置爲Always

我有3個單元測試正在測試這個方法。

當他們擊中複製文件的代碼行時:source = "Resources\\test.png"

問題

當我單獨運行單元測試,他們都通過,一切都很好。 然而,當我在運行Visual Studio的所有測試中,我得到這個運行時錯誤和單元測試失敗:

System.IO.DirectoryNotFoundException

找不到路徑的一部分「資源\測試巴紐」。

我的思考......(修訂版)

  • 可能是因爲Visual Studio中同時運行的每個單元測試在一個單獨的線程,他們都訪問同一文件在同一時間?

  • 我認爲對於每個單元測試,Visual Studio正在清除bin/Debugbin/Release文件夾。然後它複製該文件夾中所有需要的項目文件。這有時導致文件實際上不存在?

問題

我怎樣才能解決這個問題?

是否有配置的任何設置來解決這個問題?

當多個單元測試訪問同一文件時,如何在Visual Studio(和Team City)中運行所有單元測試?

+0

這可能幫助,如果你可以分享這些3次測試的整個代碼。 –

回答

1

發生了什麼事,因爲我運行批處理的單元測試時使用相對路徑來測試文件,因爲某些原因,測試運行工作目錄比運行單獨的測試時,因此它找不到目錄不同。然後

private string GetFilePath([CallerFilePath] string path = "") 
    { 
     return path; 
    } 

所以我用這個功能來構建的測試文件的絕對路徑

string projectDir = Path.GetDirectoryName(GetFilePath()); 
    string testFile = Path.Combine(projectDir, @"Resources\test.png"; 
0

我推測你的問題是,由於明確的「目錄未找到」異常,所測試的方法之一會改變目錄。文件鎖定或任何併發問題都不可能導致描述的行爲。

+0

任何單元測試都不會改變我的代碼中的目錄。我更新了這個問題,它可能會有所幫助。謝謝。 –

1

訪問相同的文件不應該是一個問題。確保您沒有清理夾具(TestSuite級別)來刪除文件。因爲從例外情況來看,運行測試後文件正在被刪除。

併發讀取操作很好,並且完全合法。如果你的單元測試覆蓋文件,那麼這是一個問題。

+0

我有一個清理,它刪除'目的地'。但是'source ='Resources \\ test.png''總是固定的並且永遠不會被刪除。 –

2

您可以嘗試按照從MSDN: Executing Unit Tests in parallel on a multi-CPU/core machine設置parallelTestCount1的說明排除多線程問題。如果測試現在通過,您已經縮小了問題範圍。

但是,如果當你在一組運行它們的測試仍然失敗 - 我覺得這是更可能的情況 - ,那麼我的建議是檢查這些測試共享任何狀態。您所描述的圖案;典型地是由被(錯誤地)共享狀態,並且狀態被這些測試修改,使一個或多個測試失敗的測試表現出的症狀(即通過在隔離時不是孤立失敗)。

0

如果單元測試,你真不該測試File.Copy(或任何文件類的方法)是否有效,因爲你沒有寫代碼。相反,你應該測試你的代碼是否與文件類型正確相互作用(即沒有將它傳遞正確的源文件名,desination文件名和覆蓋值,當你所謂的「複製」)。首先爲File類創建一個接口,併爲其實現接口的包裝器;

public interface IFileWrapper 
{ 
    void Copy(string sourceFileName,string destFileName,bool overwrite); 
    //Other required file system methods and properties here... 
} 

public class FileWrapper : IFileWrapper 
{ 
    public void Copy(string sourceFileName, string destFileName, bool overwrite) 
    { 
     File.Copy(sourceFileName, destFileName, overwrite); 
    } 
} 

然後,你應該讓你測試的類包括IFileWrapper參數(dependency injection)。在你的單元測試中,你可以使用一個像Moq這樣的模擬框架,或者你可以編寫自己的模擬器;

public class MockFileWrapper : IFileWrapper 
{ 
    public string SoureFileName { get; set; } 
    public string DestFileName { get; set; } 
    public bool Overwrite { get; set; } 
    public void Copy(string sourceFileName, string destFileName, bool overwrite) 
    { 
     SoureFileName = sourceFileName; 
     DestFileName = destFileName; 
     Overwrite = overwrite; 
    } 
} 

在實際實施中傳遞FileWrapper作爲IFileWrapper參數,但在單元測試中傳遞MockFileWrapper。通過檢查mockFileWrapper的單元測試的屬性,你現在就可以決定你的類調用是否複製,它是如何被調用。由於您不再在單元測試之間共享真實文件,您將避免測試共享狀態或潛在鎖定文件的機會。

相關問題