2014-03-04 120 views
0

我目前擁有的代碼如下:單元測試文件閱讀功能

public class SerializeFileHandler 
{ 
    public void WriteListToFile(MyProject myProject, string filePath) 
    { 
     FileStream outFile; 
     BinaryFormatter bFormatter = new BinaryFormatter(); 

     outFile = new FileStream(filePath, FileMode.Create, FileAccess.Write); 

     bFormatter.Serialize(outFile, myProject); 

     // Close file 
     outFile.Close(); 
    } 

    public MyProject ReadListFromFile(String filePath) 
    { 
     FileStream inFile; 
     BinaryFormatter bFormatter = new BinaryFormatter(); 
     MyProject myProject = new MyProject(); 

     // Open file for input 
     inFile = new FileStream(filePath, FileMode.Open, FileAccess.Read); 

     // Obtain objects from file via serialization 
     myProject = (MyProject)bFormatter.Deserialize(inFile); 

     inFile.Close(); 
     return myProject; 
    } 
} 

爲了節省我用public const string myProjectFile = "myproject.dat";的數據文件,然後到任何新的數據保存到文件,當用戶點擊保存按鈕我做serializeFileHandler.WriteListToFile();當然在括號中的參數。

我想要做的是編寫一個單元測試或多個測試,如果需要測試功能在讀取數據文件到應用程序的方面。目前,數據文件會自動加載時在程序加載(只是不上serializeFileHandler

我一直在使用Visual Studio中測試嚮導創建的測試ReadListFromFile,但我不知道我怎麼會構建測試自動化的文件閱讀功能測試。任何幫助,將不勝感激。

+0

這是有點不清楚你試過什麼,你的問題是什麼,請嘗試解決這個問題。 –

回答

0

如果是我,我就會有一個ReadListFromStream方法,然後我會注入測試流chcek是myProject的正確裝起來。

要從文件 測試,我會存根ReadListFromStream,並且確保ReadListFromFile調用它。

+0

你有沒有一個代碼可能看起來像這樣的例子?在處理C#中的序列化文件方面,我相對較新,所以它對我來說是很新的。 – user3380790

+0

打開它時,它看起來就像是該文件。看看它,通過集成測試可能會更好。創建一個東西,調用WriteToFile。用該文件中的ReadFromFile創建另一個文件,然後比較這兩個實例。你在這裏測試的是文件系統,這是一個價值很低的序列化標記,很少看到。 –

+0

我只是有點糊塗,因爲我覺得如何在我的代碼中實際實現測試時感到非常困惑。 – user3380790

0

SerializeFileHandler目前存在的問題是它對FileStream有依賴關係,而這又依賴於從文件系統讀取;爲了爲它編寫一個當前的測試,我們實際上需要與文件系統進行交互。

我們可以通過引入測試接縫來打破對文件系統的依賴關係,這將允許我們模擬/存根/僞造FileStream的行爲。在生產系統中,我們將通過SerializeFileHandler a FileStream來處理,但在單元測試中,我們會傳遞一些符合FileStream的接口SerializeFileHandler正在使用的接口,但允許我們控制用於測試目的的行爲。

首先,我們可以引入一個接口,用於與文件系統

public interface IFileStreamSource 
{ 
    Stream Open(string path, FileMode mode, FileAccess access, FileShare share); 
} 

交互流,讓SerializeFileHandler承擔這個

public class SerializeFileHandler 
{ 
    private readonly IFileStreamSource _source; 

    public SerializeFileHandler(IFileStreamSource source) 
    { 
     _source = source; 
    } 


    public void WriteListToFile(MyProject myProject, string filePath) 
    { 
     using (var stream = _source.Open(filePath, FileMode.Create, FileAccess.Write) 
     { 
      BinaryFormatter bFormatter = new BinaryFormatter(); 
      bFormatter.Serialize(stream, myProject); 
     } 
    } 

    public MyProject ReadListFromFile(String filePath) 
    { 
     MyProject myProject = null; 

     using (var stream = _source.Open(filePath, FileMode.Open, FileAccess.Read)) 
     { 
      BinaryFormatter bFormatter = new BinaryFormatter(); 

      // Obtain objects from file via serialization 
      myProject = (MyProject)bFormatter.Deserialize(stream); 
     } 

     return myProject; 
    } 
} 

依賴現在,您可以用嘲諷庫如Moq創建一個Mock<IFileStreamSource>(),可能返回MemoryStream,在您的單元測試中,並設置Open()被調用的期望值。

在你的產品代碼,你可以決定創建一個無參數的構造函數用於SerializeFileHandler是傳遞一個IFileStreamSource的實例給具有IFileStreamSource構造,當Open()被稱爲將返回的FileStream一個實例(一拉"Poor Man's Dependency Injection") ,或者您可能已經在使用IoC/Dependency Injection容器,在這種情況下,您只需爲IFileStreamSource服務註冊組件。

查看目前的代碼,我可以看到一些在ReadListFromFile中未處理的情況,例如文件不存在或文件確實存在但無法反序列化爲MyProject的實例。您可能需要編寫測試案例並相應地更新代碼:)

0

如果您需要測試與文件系統交互,您可以按照其他建議創建模擬文件系統包裝,或者創建一個獨立的文件系統測試可以使用。我更喜歡第二種方法,因爲測試更接近現實。

在測試運行之前,建立一個包含測試需要的所有文件的文件夾。然後讓測試中的代碼訪問該文件夾,而不是實際代碼訪問的文件夾。這樣,您可以閱讀文件,測試代碼如何工作(如果文件丟失),並測試文件創建。